2011-11-10 65 views
1

我想以某種方式擴展Microsoft類型_variant_t,因此它接受到其他類型的隱式/顯式轉換。要做到這一點,我寫了下面的類:顯式轉換和模板轉換運算符

class value_type 
{ 
    public: 
    /* Constructors */ 
    value_type(const std::string& str) : m_variant(str.c_str()) {} 
    template <typename Type> value_type(const Type& value) : m_variant(value) {} 

    /* Conversion operators */ 
    operator const _variant_t&() const { return m_variant; } 
    operator std::string() const { return static_cast<const char*>(m_variant); } 
    template <typename Type> operator Type() const { return static_cast<Type>(m_variant); } 
    private: 
    _variant_t m_variant; 
}; 

也就是說,如果在代碼中的_variant_t每個實例替換value_type,它「作品」相同。

讓我們考慮下面的函數,它返回一個_variant_t:如果我寫

_variant_t foo(); 

std::string bar() 
{ 
    value_type v = foo(); 
    return v; 
} 

它編譯就好了。

但是,如果我改變以前的代碼那樣:

std::string bar() 
{ 
    return value_type(foo()); 
} 

或:

std::string bar() 
{ 
    return static_cast<std::string>(value_type(foo())); 
} 

編譯失敗,出現以下消息:

configuration.cpp(41) :錯誤C2668:'std :: basic_string < _Elem,_Traits,_Ax> :: basic_string':對重載函數的模糊調用

如果我刪除template <typename Type> operator Type...行,則編譯所有內容。

現在我明白編譯器說了什麼(它不知道使用哪個運算符),但我不明白爲什麼:在轉換爲std::string時,使用operator std::string似乎是合乎邏輯的。我錯過了什麼?

謝謝。

+0

根據標準(13.3.3.1和14.5.5.2爲主)的某些段落我的(有限的)理解,我會說,你的代碼正確的,但我可能忽略了一些東西。你是否嘗試過專門化模板轉換運算符而不是重載它? –

回答

1

問題是字符串的構造函數被重載。因此,如果返回涉及調用一個字符串構造函數,則有多種選擇:參數可以轉換爲const char*,allocator<char>string

static_cast<string>(x)string(x)相同。

我想你的第一個錯誤示例應return string(foo());,不return value_type(foo());

+0

我想你對「爲什麼」是對的。但是我不能寫'std :: string(foo())',因爲'std :: string :: string()'沒有重載'_variant_t'作爲第一個參數。 – ereOn

+0

我的意思是'return value_type(foo());'似乎沒問題(用g ++)。 – visitor

+0

不幸的是,這不是一個錯字。我正在使用VC10,它在那裏失敗。 – ereOn