Contactal allows alternative assignment operator

I am trying to conditionally create an instance of an additional assignment operator. The code below works fine in clang, but not in gcc 4.7.

The problem I am facing seems very similar to the question asked here: std :: enable_if conditionally compile member function

The following is the problem I'm facing:

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

Is it possible to make it satisfy both clang and gcc 4.7? If so, how?

Compilation error when using 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> >' 
+4
source share
1 answer

You need to make enable_if dependent on the template parameter. As now, it depends only on the external template parameter in the template definition. But if you create an instance of a class from an external template, then your template of the assignment operator that is created in this class no longer depends on the template parameter, because T will already be replaced.

Just enter a dummy parameter equal to 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; } 

Using T1 only one of the places inside the template arguments enable_if<...> would be sufficient, because it already makes enable_if dependent.

However, this is not a call to your operator= , which was previously unqualified, but its declaration, which conflicts with the copy operator, so enable_if is of little use here. Just replace your code with

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

Since this operator= is a template, it will not conflict with overloading without templates. And also because this is a pattern, when you call it, the compiler will prefer a non-pattern if T is X<T> .

+2
source

Source: https://habr.com/ru/post/1403648/


All Articles