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
во вторую перегрузку. На практике libstdС++ дает:
/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); }
^~~~~~~~~~~~~~~~~~~~~~~
libС++ более прямой, с прямой детонацией 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-дружественным? Есть ли лучшее обходное решение, чем то, что описано выше?
Я нашел что-то о std::tuple_element
, но не std::get
.