Illegal user conversion?

here is the code and comment:

template<class T>
struct B
{
    B(){}

    template<class T1> operator T1() { return T1(); }

    // define this macro if your compiler fails.
#if (defined USE_MORE_TIDOUS_WAY) // (defined _MSC_VER)
    template<class T1> explicit B(B<T1> const& ) {}
    template<class T1> operator B<T1>() { return B<T1>(); }
#else
    template<class T1> B(B<T1> const& ) {}
#endif


#if 0
    ////// Explanation:

    // firstly, I want to have this convserion ctor :
    template<class T1> B(B<T1> const& ) {}

    // and the conversion function :
    template<class T1> operator T1() { return T1(); }

    // but may be T1 is too general, which could hide above
    // conversion ctor from some compilers (msvc8~10 fail, gcc 4.4.0~ is ok)

    // To overcome such case, add another conversion function :
    template<class T1> operator B<T1>() { return B<T1>(); }

    // and do not use conversion ctor, while we can still have ctor upon B<T1>
    template<class T1> explicit B(B<T1> const& ) {}

#endif
};


// test cases

template<class T> void func(T const&){};

void test()
{
    typedef B<int>      B1;
    typedef B<float>    B2; 

    B1 b1;
    B2 b2 = b1; // B1 => B2
    b1 = b2;    // B2 => B1
    b2 = b1;    // B1 => B2
    func<B1>(b2);   // B2 => B1
    func<B2>(b1);   // B1 => B2
}

int main()
{
    test();
}

So, which conversion is more standard and preferred?

+3
source share
1 answer

The problem with this conversion is:

template<class T1> operator T1() { return T1(); }

lies in the fact that it converts B to anything, so they will be compiled:

typedef B<int>      B1;
typedef B<float>    B2; 

B1 b1;
B2 b2 = b1; // B1 => B2
int x = b1; // compiles
std::string s = b2; // compiles

When looking at your test case, these examples require the assignment operator not to copy the constructor:

b1 = b2;    // B2 => B1
b2 = b1;    // B1 => B2

So, if you define your class with assignment operators like this, your test cases should work:

template<class T>
struct B
{
    B(){}
    B& operator=(B&){ return B<T>();};

    template<class T1> B(B<T1> const& ) {}
    template<class T1> B& operator=(B<T1>&){return B<T>();};

};
+1
source

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


All Articles