Que*_*tin 16 c++ sfinae language-lawyer stdtuple c++14
std::get 似乎不是SFINAE友好的,如下面的测试用例所示:
template <class T, class C>
auto foo(C &c) -> decltype(std::get<T>(c)) {
return std::get<T>(c);
}
template <class>
void foo(...) { }
int main() {
std::tuple<int> tuple{42};
foo<int>(tuple); // Works fine
foo<double>(tuple); // Crashes and burns
}
Run Code Online (Sandbox Code Playgroud)
目标是将第二次呼叫foo转向第二次超载.在实践中,libstdc ++给出:
/usr/local/bin/../lib/gcc/x86_64-pc-linux-gnu/6.3.0/../../../../include/c++/6.3.0/tuple:1290:14: fatal error: no matching function for call to '__get_helper2'
{ return std::__get_helper2<_Tp>(__t); }
^~~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
libc ++更直接,直接static_assert引爆:
/usr/include/c++/v1/tuple:801:5: fatal error: static_assert failed "type not found in type list"
static_assert ( value != -1, "type not found in type list" );
^ ~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
我真的不想实现洋葱层检查是否C是一个std::tuple专业化,并寻找T其参数内...
有没有理由std::get不对SFINAE友好?有没有比上面概述的更好的解决方法?
我发现了一些事情std::tuple_element,但没有std::get.
Bar*_*rry 17
std::get<T> 根据[tuple.elem]显然不是SFINAE友好的:
Run Code Online (Sandbox Code Playgroud)template <class T, class... Types> constexpr T& get(tuple<Types...>& t) noexcept; // and the other like overloads要求:类型
T恰好出现一次Types....否则,该计划是不正确的.
std::get<I> 也明确不是SFINAE友好的.
至于其他问题:
有没有理由
std::get不对SFINAE友好?
不知道.通常,这不是需要SFINAE编辑的一点.所以我想这不是需要做的事情.滚动查看一堆不可行的候选选项,比较容易理解硬错误.如果您认为有令人信服的理由对std::get<T>SFINAE友好,您可以提交LWG问题.
有没有比上面概述的更好的解决方法?
当然.您可以编写自己的SFINAE友好版本get(请注意,它使用C++ 17 倍表达式):
template <class T, class... Types,
std::enable_if_t<(std::is_same<T, Types>::value + ...) == 1, int> = 0>
constexpr T& my_get(tuple<Types...>& t) noexcept {
return std::get<T>(t);
}
Run Code Online (Sandbox Code Playgroud)
然后按照你的意愿去做.
不要SFINAE上std::get; 这是不允许的.
以下是两种相对友好的方法来测试你是否可以using std::get; get<X>(t):
template<class T,std::size_t I>
using can_get=std::integral_constant<bool, I<std::tuple_size<T>::value>;
namespace helper{
template<class T, class Tuple>
struct can_get_type:std::false_type{};
template<class T, class...Ts>
struct can_get_type<T,std::tuple<Ts...>>:
std::integral_constant<bool, (std::is_same_v<T,Ts>+...)==1>
{};
}
template<class T,class Tuple>
using can_get=typename helpers::can_get_type<T,Tuple>::type;
Run Code Online (Sandbox Code Playgroud)
那你的代码是:
template <class T, class C, std::enable_if_t<can_get_type<C,T>{},int> =0>
decltype(auto) foo(C &c) {
return std::get<T>(c);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
675 次 |
| 最近记录: |