2015-11-16 70 views
0

假設我們有一個原始的C風格字符串"test"。我們可以宣佈這樣的功能:C++自動構造函數調用

void printText(std::string textToPrint){ 
    std::cout << textToPrint << "\n"; 
} 

,我們可以稱之爲以如下方式:

printText("test"); 

,這應該是完全正常的,因爲參數是一個對象,而不是一個參考,所以應該在調用函數printText()時創建類似std::string("test")的臨時對象。

現在鑑於這種情況,我有以下模板:

template <typename T> 
T checkMe(Proxy<T> arg){ 
    std::cout << arg() << std::endl; 
    return arg(); 
} 

其中Proxy類的聲明如下:

template <typename T> 
class Proxy{ 
public: 
    Proxy(std::function<T&()> caller); 
    Proxy(std::shared_ptr<T> dataPtr); 
    T& operator()(); 
private: 
    std::function<T&()> m_functional; 
    std::shared_ptr<T> m_data; 
}; 

它的目的是使某些功能有兩個對象調用類型: 一個是shared_ptr到數據,另一個是功能對象,返回這種類型的數據。

現在當我想調用函數checkMe發生錯誤時,我不知道爲什麼會出現以及如何解決它。有一兩件事是:

getMe(std::make_shared<int>(255)); 

而這在我看來應該是完全正常的,作爲代理的構造函數接受shared_ptr的作爲參數,並在此基礎上創建自己。但是這給編譯器的推導錯誤。而當我打電話這樣的功能:

getMe<int>(std::make_shared<int>(255)); 

現在好了。我不知道爲什麼編譯器不能自行推斷它的類型。

第二種情況與官能對象調用它:

getMe<int>(std::bind(getNumberMult,5,6)); 

getNumberMult定義如下:發生

int xy; 
int& getNumberMult(int x, int y){ 
    return xy = x*y; 
} 

這裏轉換錯誤。有人能指出是否有可能以及如何實現給定代碼的期望行爲,並解釋我對該機制的理解有什麼問題?我想利用這個代碼如下:

getMe(std::make_shared<int>(300)); 
getMe(std::bind(getNumberMult, 6, 7)); 

編譯器錯誤:

在使用

getMe<int>(std::bind(getNumberMult, 5, 6)); 

path/to/file:36: error: C2664: 'T getMe<int>(DataProxy<T>)' : cannot convert argument 1 from 'std::_Bind<true,int &,int &(__cdecl *const)(int,int),int,int>' to 'DataProxy<int>' 
with 
[ 
    T=int 
] 
+0

實際編譯器消息的副本是強制性的。 –

+0

http://stackoverflow.com/search?q=%5Bc%2B%2B%5D+non-deducible+context –

回答

2

隨着T checkMe(Proxy<T> arg)arg應該是Proxy<T>(或繼承它)。

編譯器不檢查無限的可能性來測試每個Proxy<T>可以從給定的參數構造。

0

因此,我通常知道爲什麼如此,我該怎麼做才能解決這個問題。

考慮以下對象:

struct Test{ 
    Test(std::string someString){} 
}; 

因此,我們需要的std :: string只是爲了構建這個類的對象。

我們可以不用在下列方式明確創建std::string

int main(){ 
    Test someVariable("someRawString"); 
} 

這是要去工作,這是完全沒問題。會發生什麼引擎蓋是:

  • 編譯器符合指令Test
  • 它看到的創建對象,即給定的參數是通過構造函數所需的類型不
  • 因爲事實上,需要的參數
  • 是值,而不是引用(const引用也可以),它會創建std::string類型的臨時對象,並將此臨時對象傳遞給構造函數
  • 對象已成功創建。

現在讓我們考慮功能:

void someTestFunction(Test someTest){} 

它需要Test類型的對象,是從std::string

鑑於構成,即它應該是罰款下列方式來調用這個函數:

someTestFunction("someRawText"); 

但它不好。這給我們轉換參數的錯誤。原因很簡單:在將參數傳遞給函數時,C++只允許轉換一個步驟。所以編譯器可以:

  • 投原字符串std::string
  • 創建Test對象與std::string

但它不能:

  • 投原字符串std::string
  • std::stringTest(太多con版本)
  • 調用函數測試

完全一樣的事情發生了與給定的代碼。爲了使其工作,我們應該使用:

getMe<int>(std::make_shared<int>(300)); 
getMe<int>(std::function<int&()>(std::bind(getNumberMult, 6, 7))); 

爲什麼這樣呢?

std::make_shared<int>返回類型爲std::shared_ptr<int>,因此不需要轉換就可以調用函數。

std::bind...具有不同於std::function的返回類型,它具有它自己的實現定義的返回類型。這就是爲什麼在這裏需要第二次強制轉換,這是C++不允許的。當我們明確地施放它時,只需要一次隱式轉換,並且一切正常。