【发布时间】:2017-06-02 04:28:32
【问题描述】:
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
}
目标是将第二次调用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); }
^~~~~~~~~~~~~~~~~~~~~~~
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" );
^ ~~~~~~~~~~~
我真的不想实现洋葱层检查 C 是否是 std::tuple 特化,并在其参数中寻找 T...
std::get 是否有理由对 SFINAE 不友好?有没有比上面列出的更好的解决方法?
我找到了something about std::tuple_element,但没有找到std::get。
【问题讨论】:
-
“SFINAE”的“S”部分代表“替代”。在这里,将模板参数替换为第一个
foo没有问题。T是double。C就是那个元组类型。替换成功! -
@SamVarshavchik 但返回类型涉及形成无效的函数调用。如果
std::get对 SFINAE 友好(即,让自己脱离无效调用的重载集),这将触发替换失败。因此我的问题。 -
@SamVarshavchik see this snippet 为例。
-
当
std::get的模板参数是一个类时,它的返回类型是显式的,而不是像元组索引常量那样是auto。所以,decltype()很高兴。template< class T, class... Types > constexpr T& get(tuple<Types...>& t);-- 游戏结束。 -
@SamVarshavchik 你在干什么。
标签: c++ c++14 language-lawyer sfinae stdtuple