使用msvc2013的decltype模板出错

时间:2016-01-04 16:02:32

标签: c++ templates visual-studio-2013 sfinae decltype

我正在尝试使用以下构造来检查是否存在基于我之前获得的this answer的成员函数:

template <typename T, class = double>
struct has_a : std::false_type {};

template <typename T>
struct has_a<T, decltype(std::declval<T>().a())> : std::true_type {};

这适用于gcc 4.9.2,但无法使用msvc2013进行编译:

  

错误C2228:'。a'的左边必须有class / struct / union类型   'add_rvalue_reference&LT; _Ty&GT; ::类型'

似乎(?)这样的编译器错误,因为declval特别应该在未评估的decltype表达式(see here)内工作。有没有已知的解决方法?

1 个答案:

答案 0 :(得分:1)

MSVC 2013的尾随返回类型解析器似乎比表达式SFINAE系统更完整,如果以下面的方式重构检查器(following T.C's suggestion),它在msvc2013和gcc 4.9.2上都按预期工作:

template <typename T>
struct has_a_impl
{
    template<typename U>
    static auto test(U* p) -> decltype(p->a()); // checks function existence
    template<typename U>
    static auto test(...) -> std::false_type;

    using type = typename std::is_floating_point<decltype(test<T>(0))>::type; // checks return type is some kind of floating point
};

template <typename T>
struct has_a : has_a_impl<T>::type {};

此语法的另一个好处是返回类型检查可以使用任何type_traits,因此您不必检查单一类型的返回值(例如,double)。