2011-12-20 80 views
-1

這裏是一個很小的代碼,顯示問題:模板拷貝構造函數的錯誤

template<typename To, typename From> To convert(const From& x); 

struct A 
{ 
    int value; 
    template<typename T> A(const T& x) { value = convert<A>(x).value; } 
}; 

struct B : public A { }; 

int main() 
{ 
    B b; 
    A a = b; 
} 

它給我:undefined reference to 'A convert<A, B>(B const&)'

正如預期的那樣,因爲我刪除默認的拷貝構造函數。但是,如果我將此行添加到A

A(const A& x) { value = x.value; } 

我得到相同的錯誤。如果我嘗試這樣做是這樣的:(添加模板專門化)

template<> A(const A& x) { value = x.value; } 

我得到:error: explicit specialization in non-namespace scope 'struct A'

如何解決?

我的編譯器是MinGW的(GCC)4.6.1

編輯:

convert功能從衆多類型轉換爲A,然後再返回。問題在於,由於繼承原因,編寫從BA的轉換函數是沒有意義的。如果我從A中刪除了調用convert的行,它就行了。這個想法是在的所有時間不會從A繼承,因爲這些默認的構造函數應該足夠了。

回答

3

據我所知,當b通過,因爲b不是A的對象,所以不調用複製構造函數,而是調用模板構造函數。

但是,如果派生類的對象傳遞,你想要的A拷貝構造函數被調用。

對於這一點,有一種使用<type_traits>(C++ 0X)一種溶液:

#include <type_traits> 

template<typename To, typename From> To convert(const From& x); 

struct A 
{ 
    int value; 
    template<typename T> A(const T& x, 
     const typename std::enable_if<!std::is_base_of<A,T>::value, bool>::type = false) 
    { value = convert<A>(x).value; } 
    A(){} 
}; 

struct B : public A { }; 

int main() 
{ 
    B b; 
    A a = b; 
} 

模板被禁用爲什麼從A派生的類的一個對象被傳遞,所以唯一可用的構造是複製構造函數。

0

那麼,「未定義的參考」應該很容易通過鏈接功能的實現來解決!

注意:根據情況,返回副本將觸發堆棧溢出。編輯:國際海事組織,你的設計是有缺陷的,你已經把A以外的建設邏輯轉移到convert;編號:

編輯:而不是這個,你應該在A中提供特定的轉換構造函數。如果傳入的類型是從A派生的(您可以使用type_traits之一),那麼要麼禁止轉換構造函數,要麼就是這樣。例如,如果您可以從int構建A,請在A本身中提供特定的構造函數。

+0

目前尚不清楚。請仔細閱讀編輯。謝謝你,反正。 – 2011-12-20 13:34:40

0

您可以通過定義的轉換功能,可以解決它:

template<typename To, typename From> const To& convert(const From& x) 
{ 
    return x; 
} 
0

正如預期的那樣,因爲我刪除默認的拷貝構造函數。

否;雖然你確實需要替換默認的拷貝構造函數,但是它的省略會導致不同類型的問題(並且只有當你有那種需要它的調用代碼時)。

錯誤你彙報:

undefined reference to 'A convert<A, B>(B const&) 

是一個連接錯誤。它告訴你,你實際上並沒有一個convert函數。

error: explicit specialization in non-namespace scope 'struct A' 

你是第一次瞭解如何恢復默認的複製構造函數。但是,這仍然與鏈接器錯誤無關。

+0

爲什麼你需要替換默認的拷貝構造函數?它仍然存在,並且將選擇代替模板,如果源對象的類型是'A'。 – 2011-12-20 13:39:07

+0

你肯定它仍然存在?這完全不符合我的經驗。 – 2011-12-20 17:07:32

+0

[是](http://ideone.com/axKpn)。根據C++ 11,12.8/8,「如果類定義不明確聲明拷貝構造函數,沒有用戶聲明的移動構造函數, 並沒有用戶聲明的舉動賦值運算符,拷貝構造函數是隱式聲明爲 默認。「 – 2011-12-20 17:16:23