以下特征类用于检查通用 vector 是否具有operator[](int)operator()(int):

template<typename ...> using void_t = void;

template< typename, typename = void>
struct has_bracket_operator : public std::false_type {};

template<typename V>
struct has_bracket_operator<V, void_t<decltype(std::declval<V>()[int{}])> >
    : public std::true_type{};

template<typename, typename = void>
struct has_parenthesis_operator : public std::false_type {};

template<typename V>
struct has_parenthesis_operator<V, void_t<decltype(std::declval<V>()(int{}))> >
    : public std::true_type{};

看来compile well in gcc 5.1.0

另一方面,在最新的MSVC下载中(Microsoft Visual Studio Community 2015 RC版本14.0.22823.1 D14REL),我收到has_parenthesis_operator模板的编译器错误,内容为:



而且,我发现以下版本最好完全不编译(请注意,使用operator[](int{})代替[int{}],并且括号类似):
template<typename V>
struct has_bracket_operator<V, void_t<decltype(std::declval<V>().operator[](int{}))> >
    : public std::true_type{};

//...

template<typename V>
struct has_parenthesis_operator<V, void_t<decltype(std::declval<V>().operator()(int{}))> >
    : public std::true_type{};

错误消息是



问题:
  • 这是一个错误吗?还是我做错了什么(哪个gcc以某种方式接受)?
  • 是否可以使用以上技术(尤其是void_t)来解决?
  • 如果无法解决,如何在MSVC中设置备用SFINAE检查(我尝试了很多this,但并未真正成功-至少在MSVC中)?
  • 最佳答案

    如@ T.C。所述,通过void_t<decltype(...)>的上述方法需要expression SFINAE,在当前版本的MSVC 2015中不可用。

    这是从here提取的SFINAE表达式的当前实现状态:





    而且,这是使用传统SFINAE(灵感来自here)针对上述特征的一种老式解决方法:

    template<typename C, typename Ret, typename... Args>
    struct has_parenthesis_operator<C, Ret(Args...)>
    {
    private:
        template<typename T>
        static constexpr auto check(T*)
            -> typename std::is_same<std::decay_t<decltype(std::declval<T>().operator()(std::declval<Args>()...))>, Ret>::type;
    
        template<typename> static constexpr std::false_type check(...);
    
        typedef decltype(check<C>(0)) type;
    
    public:
        static constexpr bool value = type::value;
    };
    

    例如可以用作
    template<typename V
           , typename = std::enable_if_t<has_bracket_operator<V, double(int)>::value>
    auto get(V const& v, int i)
    {
        return v[i];
    }
    

    这将检查所传递的 vector 类型是否具有成员double operator[](int),如果存在则称为成员(否则,可以使用括号运算符执行类似操作)。



    关于@Yakk的评论:我遇到了MSVC的 __if_exists statement特殊功能,它似乎完成了与上述操作类似的任务。

    关于c++ - 用于检测成员函数的C++特征类:MSVC 2015 RC中的编译器错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30856989/

    10-13 07:38