我喜欢autoC++ 11.太棒了.但它有一个不一致,真的让我紧张,因为我一直绊倒它:
int i = 3; // i is an int with value 3
int i = int{3}; // i is an int with value 3
int i(3); // i is an int with value 3 (possibly narrowing, not in this case)
int i{3}; // i is an int with value 3
auto i = 3; // i is an int with value 3
auto i = int{3}; // i is an int with value 3
auto i(3); …Run Code Online (Sandbox Code Playgroud) 在以下代码中
#include <initializer_list>
#include <utility>
template<typename T> void f(T&& x) {}
template<typename T> void g(std::initializer_list<T> x) {}
int main()
{
auto x = {0}; // OK
auto&& y = {0}; // OK
g(x); // OK
g(std::move(x)); // OK
g({0}); // OK
f(x); // OK
f(std::move(x)); // OK
f({0}); // failure
return 0;
}
Run Code Online (Sandbox Code Playgroud)
rvalue initializer_list可以推导,auto但不能推断template.
为什么C++会禁止这个?
初始化列表表达式非常便于初始化C++容器:
std::vector<int>({1, 2, 3})
Run Code Online (Sandbox Code Playgroud)
......但似乎一个括号内的初始化列表表达式,如{1,2,3}将只绑定到需要的功能std::initializer_list<int>-它并不似乎绑定到一个通用(转发)参考:
template <class T>
void foo(T&& v)
{
std::vector<int>(std::forward<T>(v));
}
int main()
{
foo({1, 2, 3})
}
Run Code Online (Sandbox Code Playgroud)
这输出:
test2.cpp:11:6: note: template<class U> void foo(U&&)
test2.cpp:11:6: note: template argument deduction/substitution failed:
test2.cpp:33:13: note: couldn't deduce template parameter ‘U’
Run Code Online (Sandbox Code Playgroud)
(这是GCC 4.7.2的结果.)
遗憾的是,这意味着我们无法转发初始化列表表达式.既然这样做很方便,我想问为什么这不起作用?为什么括号封闭的初始化列表表达式不能绑定到转发引用?或者这是允许的,也许我的编译器太老了?
为什么构造函数(4)std::variant来自http://en.cppreference.com/w/cpp/utility/variant/variant?似乎它会在代码中引起很多歧义,否则可以通过显式来避免.例如,cppreference上的代码示例突出显示用户可能不会注意到的可能的歧义(第三行)
variant<string> v("abc"); // OK
variant<string, string> w("abc"); // ill-formed, can't select the alternative to convert to
variant<string, bool> w("abc"); // OK, but chooses bool
Run Code Online (Sandbox Code Playgroud)
有些情况下绝对需要吗?
另一个问题是为什么需要从同一个cppreference页面构造函数(6)和(8).(5)和(7)不符合(6)和(8)的目的吗?我可能误解了他们的用法..
对于读者来说,我在问题中提到的构造函数是
constexpr variant(); // (1) (since C++17)
variant(const variant& other); // (2) (since C++17)
variant(variant&& other); // (3) (since C++17)
template< class T > // (4) (since C++17)
constexpr variant(T&& t);
template< class T, class... Args >
constexpr explicit variant(std::in_place_type_t<T>, Args&&... args); // (5) (since C++17)
template< class T, …Run Code Online (Sandbox Code Playgroud) 我有以下模板功能:
template<typename T> void foo2(T t) {}
Run Code Online (Sandbox Code Playgroud)
我知道我不能用它来调用它:
foo2({1,2,3});
Run Code Online (Sandbox Code Playgroud)
因为初始化列表是模板参数的非推导上下文.我必须使用:
foo2<std::initializer_list<int>>({1,2,3});
Run Code Online (Sandbox Code Playgroud)
但我也可以用:
foo2(std::initializer_list<int>({1,2,3}));
Run Code Online (Sandbox Code Playgroud)
这让我想知道有什么区别:{1,2,3}和std::initializer_list<int>({1,2,3})?