vpo*_*yev 6 c++ templates language-lawyer constexpr
海湾合作委员会(5.3)和Clang(3.8)声称第一行test是坏的,但第二行是好的.MSVC(2015.2)说,两者都是无效的.
template< typename N, typename T >
void f( N n, T t ) { std::get< n >( t ); }
void test() {
std::get< std::integral_constant< size_t, 0 >() >( std::make_tuple( 123 ) ); // not ok
f( std::integral_constant< size_t, 0 >(), std::make_tuple( 123 ) ); // ok for gcc, clang, but not msvc
}
Run Code Online (Sandbox Code Playgroud)
根据标准,究竟是什么区别?此代码合法开头吗?
第一行的clang错误:
In file included from main.cpp:2:
/usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.3.0/../../../../include/c++/5.3.0/tuple:874:34: error: no matching function for call to '__get_helper2'
{ return std::forward<_Tp&&>(std::__get_helper2<_Tp>(__t)); }
^~~~~~~~~~~~~~~~~~~~~~~
main.cpp:10:10: note: in instantiation of function template specialization 'std::get<std::integral_constant<unsigned long, 0> (), int>' requested here
std::get<std::integral_constant<size_t, 0>()>( std::make_tuple( 123 ) ); // not ok
^
/usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.3.0/../../../../include/c++/5.3.0/tuple:856:5: note: candidate template ignored: could not match '_Tuple_impl' against 'tuple'
__get_helper2(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
^
/usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.3.0/../../../../include/c++/5.3.0/tuple:861:5: note: candidate template ignored: could not match '_Tuple_impl' against 'tuple'
__get_helper2(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
^
1 error generated.
Run Code Online (Sandbox Code Playgroud)
gcc错误:
In file included from main.cpp:2:0:
/usr/local/include/c++/5.3.0/tuple: In instantiation of 'constexpr _Tp&& std::get(std::tuple<_Elements ...>&&) [with _Tp = std::integral_constant<long unsigned int, 0ul>(); _Types = {int}]':
main.cpp:10:75: required from here
/usr/local/include/c++/5.3.0/tuple:874:57: error: no matching function for call to '__get_helper2(std::tuple<int>&)'
{ return std::forward<_Tp&&>(std::__get_helper2<_Tp>(__t)); }
^
/usr/local/include/c++/5.3.0/tuple:856:5: note: candidate: template<class _Head, long unsigned int __i, class ... _Tail> constexpr _Head& std::__get_helper2(std::_Tuple_impl<__i, _Head, _Tail ...>&)
__get_helper2(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
^
/usr/local/include/c++/5.3.0/tuple:856:5: note: template argument deduction/substitution failed:
/usr/local/include/c++/5.3.0/tuple:874:57: note: mismatched types 'std::integral_constant<long unsigned int, 0ul>()' and 'int'
{ return std::forward<_Tp&&>(std::__get_helper2<_Tp>(__t)); }
^
/usr/local/include/c++/5.3.0/tuple:874:57: note: 'std::tuple<int>' is not derived from 'std::_Tuple_impl<__i, std::integral_constant<long unsigned int, 0ul>(), _Tail ...>'
/usr/local/include/c++/5.3.0/tuple:861:5: note: candidate: template<class _Head, long unsigned int __i, class ... _Tail> constexpr const _Head& std::__get_helper2(const std::_Tuple_impl<__i, _Head, _Tail ...>&)
__get_helper2(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
^
/usr/local/include/c++/5.3.0/tuple:861:5: note: template argument deduction/substitution failed:
/usr/local/include/c++/5.3.0/tuple:874:57: note: mismatched types 'std::integral_constant<long unsigned int, 0ul>()' and 'int'
{ return std::forward<_Tp&&>(std::__get_helper2<_Tp>(__t)); }
^
/usr/local/include/c++/5.3.0/tuple:874:57: note: 'std::tuple<int>' is not derived from 'const std::_Tuple_impl<__i, std::integral_constant<long unsigned int, 0ul>(), _Tail ...>'
Run Code Online (Sandbox Code Playgroud)
tl; dr我认为gcc和clang在这两种情况下的行为都是正确的.
两次通话之间存在细微差别.让我添加一个别名来说明:
using Zero = std::integral_constant<size_t, 0>;
auto tuple = std::make_tuple(123);
Run Code Online (Sandbox Code Playgroud)
当你写:
std::get<Zero()>(tuple);
Run Code Online (Sandbox Code Playgroud)
Zero()是一种类型.这是一个返回的nullary函数Zero.因此,您正在调用的std::get类型为:std::get<T>().由于tuple该类型中没有元素,因此Zero()这是一个错误.
另一方面,当你写:
Zero n;
std::get<n>(tuple);
Run Code Online (Sandbox Code Playgroud)
n不是一种类型 - 它只是一种价值.因为std::integral_constant有一个constexpr operator size_t(),一个被使用,你最终打电话std::get<I>(),这是你所期望的.
通过简单地使用大括号初始化也可以实现同样的目的:
std::get<Zero{}>(tuple);
Run Code Online (Sandbox Code Playgroud)
因为Zero{}绝对不是一种类型.
| 归档时间: |
|
| 查看次数: |
355 次 |
| 最近记录: |