2010-11-16 3 views
3

здесь код и комментарий:незаконное пользовательское преобразование?

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(); 
} 

Итак, что преобразование более стандартной сообразуйтесь и предпочтительным?

+0

Что-то взрывное попало в ваше форматирование, вы можете немного почистить его? –

+1

Можете ли вы объяснить, что вы пытаетесь сделать с этим? Вероятно, есть лучший способ. –

+0

'template оператор T1();': Это говорит о том, что вы можете конвертировать 'B ' в любой тип вообще. Как это полезно? – aschepler

ответ

1

Проблема с этим преобразованием:

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

является то, что он будет конвертировать B ни к чему, так что они будут компилировать:

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

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

Глядя на тестовом случае, эти примеры требуют оператора присваивания не копировать конструктор:

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

Так что, если вы определяете свой класс с опцией назначения например, ваши тестовые примеры должны работать:

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>();}; 

}; 
Смежные вопросы