MSVC - 使用void_t进行成员检测无法正常工作

时间:2016-11-14 16:46:29

标签: c++ c++11 templates visual-c++

我前几天遇到过这个问题。

#include <iostream>
#include <type_traits>
using namespace std;

template<typename... Ts> struct make_void { typedef void type; };
template<typename... Ts> using void_t = typename make_void<Ts...>::type;

template <class, class = void>
struct is_func_chrend_ : std::false_type {};

template <class T>
struct is_func_chrend_<T, ::void_t<decltype(std::declval<T>().NextTile())>> : std::true_type {};

template <class = void, class = void>
struct is_addable : std::false_type {};

template <class T>
struct is_addable<T, ::void_t<decltype(std::declval<T>() + std::declval<T>())>> : std::true_type {};

int main() {
    cout << is_addable<int>::value << endl;
    return 0;
}

在MSVC中编译时显示0,如果在clang或gcc中编译,则显示1。 完全删除is_func_chrend_会使is_addable再次正常工作。

Makeshift void_t仅用于符合C ++ 11的编译器。

1 个答案:

答案 0 :(得分:2)

MSVC尚未发布符合C ++ 11标准的编译器。

他们最大的问题是decltype在SFINAE环境中使用。

他们定期改善情况,使越来越多decltype个案件有效,但不可靠。

破坏的方式经常会在出现问题时产生误报和漏报,并且失败是非本地的,因为您以前使用SFINAE表达式的方式可能会改变下次成功或失败的方式。

您无法安全地在MSVC中使用基于decltype的SFINAE,除非您仔细解码您的特定版本的MSVC可以处理的内容,并且永远不会离开这些边界。我个人发现他们对什么有用以及什么不足以让我觉得我可以依赖使用它的描述。