使`std :: get`与SFINAE配合使用 [英] Making `std::get` play nice with SFINAE

查看:117
本文介绍了使`std :: get`与SFINAE配合使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

std::get似乎对SFINAE不友好,如以下测试用例所示:

std::get does not seem to be SFINAE-friendly, as shown by the following test case:

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
}

在Coliru上直播

目标是将对foo的第二个调用转移到第二个重载.实际上,libstdc ++给出:

The goal is to divert the second call to foo towards the second overload. In practice, libstdc++ gives:

/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 ++更直接,直接引爆即可:

libc++ is more direct, with a straight static_assert detonation:

/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 ...

I would really like not to implement onion layers checking whether C is an std::tuple specialization, and looking for T inside its parameters...

std::get是否对SFINAE不友好?是否有比上面概述的方法更好的解决方法?

Is there a reason for std::get not to be SFINAE-friendly? Is there a better workaround than what is outlined above?

我发现关于std::tuple_element的一些信息,而不是std::get.

推荐答案

std::get<T>显然对SFINAE不友好:

std::get<T> is explicitly not SFINAE-friendly, as per [tuple.elem]:

template <class T, class... Types>
  constexpr T& get(tuple<Types...>& t) noexcept;
// and the other like overloads

要求:类型TTypes...中仅出现一次. 否则,程序格式错误.

Requires: The type T occurs exactly once in Types.... Otherwise, the program is ill-formed.

std::get<I>也明确不支持SFINAE.

std::get<I> is also explicitly not SFINAE-friendly.

关于其他问题:

std::get是否对SFINAE不友好?

Is there a reason for std::get not to be SFINAE-friendly?

不知道.通常,这不是需要进行SFINAE处理的一点.因此,我认为这不是需要做的事情.硬错误比滚动一堆不可行的候选选项更容易理解.如果您认为std::get<T>对SFINAE友好是有说服力的,则可以提交有关此问题的LWG问题.

Don't know. Typically, this isn't a point that needs to be SFINAE-ed on. So I guess it wasn't considered something that needed to be done. Hard errors are a lot easier to understand than scrolling through a bunch of non-viable candidate options. If you believe there to be compelling reason for std::get<T> to be SFINAE-friendly, you could submit an LWG issue about it.

是否有比上面概述的方法更好的解决方法?

Is there a better workaround than what is outlined above?

好的.您可以编写自己的get SFINAE友好版本(请注意,它使用C ++ 17

Sure. You could write your own SFINAE-friendly verison of get (please note, it uses C++17 fold expression):

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);
}

然后根据需要进行处理.

And then do with that as you wish.

这篇关于使`std :: get`与SFINAE配合使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆