有条件地启用备用赋值运算符

All*_*lan 5 c++ template-specialization c++11

我试图有条件地实例化一个额外的赋值运算符.下面的代码在clang中工作正常,但在gcc 4.7中没有.

我遇到的问题似乎与此处提出的问题非常相似:std :: enable_if有条件地编译成员函数

以下说明了我遇到的问题:

#include <type_traits>

template<typename T>
struct StrangerTypeRules;

template<typename T>
struct X;

template< >
struct StrangerTypeRules < unsigned > {
    typedef unsigned type;
};

template< >
struct StrangerTypeRules < bool > {
    typedef X<bool> type;
};

template<typename T>
struct X {
    // In the non-trivial version of my code, I can not use the
    // default assignment operator, therefor I need to define this one
    X& operator=( const X<T>& rhs ) {
        return *this;
    }

    // Alternative assignment oprtator, must only exists if it is
    // different from the assignment operator above
    template<typename =
        typename std::enable_if<
            ( !std::is_same<
                X<T>,
                typename StrangerTypeRules<T>::type
            >::value ),
            X<T>
        >::type
    >
    X<T> & operator=( const typename StrangerTypeRules <T>::type& rhs ) {
        return *this;
    }
};

int main(int argc, const char *argv[])
{
    X<unsigned> x1, x2;

    x1 = 4;
    x2 = x1;

    X<bool> x3, x4; // compile error in gcc 4.7 with -std=c++11
    //x3 = x4;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这可以通过满足clang和gcc 4.7的方式完成吗?如果是这样,怎么样?

使用gcc时编译错误:

test.cxx: In instantiation of ‘struct X<bool>’:
test.cxx:52:13:   required from here
test.cxx:38:12: error: no type named ‘type’ in ‘struct std::enable_if<false, X<bool> >’
Run Code Online (Sandbox Code Playgroud)

Joh*_*itb 2

您需要使enable_if依赖于模板参数。现在,它仅依赖于模板定义中的外部模板参数。但是,如果您从外部模板实例化一个类,那么实例化到该类中的赋值运算符模板就不再依赖于模板参数,因为它T已经被替换了。

只需引入一个虚拟参数等于T

template<typename T1 = T, typename =
    typename std::enable_if<
        ( !std::is_same<
            X<T1>,
            typename StrangerTypeRules<T1>::type
        >::value ),
        X<T1>
    >::type
>
X<T1> & operator=( const typename StrangerTypeRules <T1>::type& rhs ) {
    return *this;
}
Run Code Online (Sandbox Code Playgroud)

T1仅在模板参数中的一个位置使用enable_if<...>就足够了,因为这已经产生了enable_if依赖。

然而,以前正确的不是对 your 的调用,而是它的声明,它与复制赋值运算符冲突,因此在这里几乎没有用处。只需将您的代码替换为operator=enable_if

template<typename T1 = T>
X<T1> & operator=( const typename StrangerTypeRules <T1>::type& rhs ) {
    return *this;
}
Run Code Online (Sandbox Code Playgroud)

由于这operator=是模板,因此不会与非模板重载发生冲突。而且因为它是一个模板,所以当您调用它时,编译器会更喜欢非模板 if Tis X<T>