在浏览gcc当前新C++ 11标头的实现时,我偶然发现了"......"令牌.您可以检查,以下代码编译正常 [通过ideone.com].
template <typename T>
struct X
{ /* ... */ };
template <typename T, typename ... U>
struct X<T(U......)> // this line is the important one
{ /* ... */ };
Run Code Online (Sandbox Code Playgroud)
那么,这个令牌的含义是什么?
编辑:看起来如此修剪"......"的问题标题为"......",我的意思是"......".:)
UPDATE1: C++ 17构造附加型扣-这并不意味着自由功能是较差的溶液.
UPDATE2: C++ 17增加了保证副本省略(副本甚至没有在概念上发生).因此,使用C++ 17,我的代码实际上可以工作并具有最佳性能.但Martinho使用支撑初始化来获得返回值的代码仍然是我认为的更清洁的解决方案.但请查看Barry的回答以及TC的评论
旧帖子:类型推导不适用于构造函数(至少在包含C++ 11之前).常见的解决方案是依靠RVO(返回值优化)并编写make_XYZ模板函数,将其参数转发给构造函数.一个例子是std::make_tuple.
任何模板acrobat谁知道一个解决方法,以便在nocopy策略阻碍时使其工作?有效的解决方案仍然必须允许RVO发生.
另外,对于任何make_XYZ的要求是否会随C++ 14消失?
#include <iostream>
template <typename T>
struct XYZ
{
// remove following two lines to make the code compile
XYZ (XYZ const & rhs) = delete;
XYZ (XYZ && rhs) = delete;
T i;
XYZ (T i):i(i)
{
}
};
template <typename T>
XYZ<T> make_XYZ (T && i)
{
return XYZ<T>(std::forward<T>(i));
}
int main ()
{
auto x = make_XYZ(1);
std::cout << x.i << …Run Code Online (Sandbox Code Playgroud) 这里有很多关于何时可以进行RVO的讨论,但关于什么时候实际完成的情况并不多.如上所述,根据标准,无法保证RVO,但有没有办法保证RVO优化成功或相应的代码无法编译?
到目前为止,当RVO失败时,我部分成功地使代码发出链接错误.为此,我声明了复制构造函数而没有定义它们.显然,在我需要实现一个或两个拷贝构造函数的非罕见情况下,这既不强大也不可行,即x(x&&)和x(x const&).
这让我想到了第二个问题:为什么选择编译器编写器来在用户定义的复制构造函数到位时启用RVO,而不是仅在存在默认复制构造函数时?
第三个问题:是否有其他方法可以为普通数据结构启用RVO?
最后一个问题(承诺):您是否知道任何编译器使我的测试代码表现得与我用gcc和clang观察到的不同?
下面是gcc 4.6,gcc 4.8和clang 3.3的一些示例代码,用于显示问题.该行为不依赖于常规优化或调试设置.当然选项--no-elide-constructors会按照它说的做,即关闭RVO.
#include <iostream>
using namespace std;
struct x
{
x () { cout << "original x address" << this << endl; }
};
x make_x ()
{
return x();
}
struct y
{
y () { cout << "original y address" << this << endl; }
// Any of the next two constructors will enable RVO even if only …Run Code Online (Sandbox Code Playgroud) 在下面的代码中,我不允许声明一个显式的 ctor,因为编译器说我在复制初始化上下文中使用它(clang 3.3和gcc 4.8).我试图通过使ctor非显式,然后将复制构造函数声明为已删除来证明编译器是错误的.
编译器是错误还是有其他解释?
#include <iostream>
template <typename T>
struct xyz
{
constexpr xyz (xyz const &) = delete;
constexpr xyz (xyz &&) = delete;
xyz & operator = (xyz const &) = delete;
xyz & operator = (xyz &&) = delete;
T i;
/*explicit*/ constexpr xyz (T i): i(i) { }
};
template <typename T>
xyz<T> make_xyz (T && i)
{
return {std::forward<T>(i)};
}
int main ()
{
//auto && x = make_xyz(7);
auto && …Run Code Online (Sandbox Code Playgroud) 这应该是使用可变参数模板的常见情况,例如当树行走的子节点是可变参数模板参数时.我找到了许多相关的问题和答案,但要么它们是略有不同的东西,要么它们是相同的东西,我没有得到它.现在来问题了.我有一个像这样的非变量元组
template <class E, class T1, class T2, class T3, etc...>
struct X;
Run Code Online (Sandbox Code Playgroud)
我正在重载函数以具有专门的行为,这取决于这样的元组的第一个元素是指针类型或向量指针类型.这工作正常,但如果我将模板参数打包到单个可变参数模板参数中,则重载变得模糊不清.这是错误消息:
variadic.cpp:42:17: error: ambiguous overload for ‘operator<<’ in ‘std::cout << y’
variadic.cpp:42:17: note: candidates are:...
Run Code Online (Sandbox Code Playgroud)
编译器应该更喜欢X<vector<V*>*,T*...>在X<H*,T*...>当它试图匹配vector<double*>*的元组的第一个元素.
我可以使用enable_if消除歧义,并且事情再次起作用.但是,我想了解错误,如果可能的话,找到其他方法然后启用enable_if.这是代码:
#include <iostream>
#include <vector>
#include <boost/type_traits/is_fundamental.hpp>
#include <boost/utility/enable_if.hpp>
using namespace std;
template <typename ... T>
struct X;
template <>
struct X <>
{
};
template <typename H, typename ... T>
struct X<H*,T*...> : public X<T*...>
{
H* value;
X(H* value, T*... args)
: value(value), …Run Code Online (Sandbox Code Playgroud) 从概念上讲,我认为以下内容并不侵犯隐私。但这是被禁止的。
struct A
{
int a;
int b;
int c;
};
struct B
{
int a;
int b;
private:
int c;
};
int main (int argc, char * argv[])
{
auto a = A{1,2,3}; //ok
auto b = A{1,2}; //ok
auto c = B{1,2,3}; //error
auto d = B{1,2}; //error
return 0;
}
Run Code Online (Sandbox Code Playgroud)
添加手动构造函数将允许对私有成员进行大括号初始化。但聚合和 Pod 的优点在于您需要的编码量很少,因此这很烦人。
另一方面,我认为这是一种隐私侵犯,但这是标准允许的。
Visual Studio(至少VisualStudio 2010)将目标平台设置存储在*.suo文件中,显然不受版本控制.
在我的情况下,这对于中央构建来说没有问题,因为它在msbuild上使用命令行选项,强制目标平台根据需要为x86.
但是,如果一位同事检查我的项目,他将总是为AnyCPU构建并测试它.因为他没有*.suo文件VisualStudio将使用默认设置.
不管是不是,同事有义务测试x86.
是否有一种简单的方法可以安全地保留目标平台的解决方案?强制默认值的环境变量不是我们需要的,但足够好且足够简单.
要理解这个问题,请先阅读此答案.
我检查了不同的历史make_tuple实现(包括2012年的clang版本).在C++ 17之前我会期望它们,return {list of values ... }但它们都会在返回之前构造元组.它们都是非常简化的当前cppreference示例:
template <class... Types>
auto make_tuple(Types&&... args)
{
return std::tuple<special_decay_t<Types>...>(std::forward<Types>(args)...);
}
Run Code Online (Sandbox Code Playgroud)
它没错,但返回大括号初始化的重点是直接构造返回的对象.在C++ 17之前,没有保证的复制省略甚至在概念上消除了临时性.但即使使用C++ 17,我也不一定会期望花括号在这个例子中消失.
为什么在任何C++ 11/14实现中都没有花括号?换句话说,为什么不呢
template <class... Types>
std::tuple<special_decay_t<Types>...> make_tuple(Types&&... args)
{
return {std::forward<Types>(args)...};
}
Run Code Online (Sandbox Code Playgroud) ...比如Algol68或Smalltalk?这将解决的问题是初始化一个const变量,其值在if-then-else语句中确定.
是的,我知道,C++没有这样定义.但是阻碍什么呢?将if-expression重新定义为if语句会破坏向后兼容性吗?或者难以消除所需的语言文档更改的歧义?
例:
auto const x = if (some condition)
{
expression 1;
expression 2;
expression 3;
}
else
{
expression 4;
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下我不能这样做
auto const x = (some condition) ? expression1 : expression2;
Run Code Online (Sandbox Code Playgroud)