2016-05-16 240 views
4

我不明白爲什麼編譯器會選擇我的Production類的複製構造函數,並且沒有其他候選函數。 我做了一個小例子來演示錯誤:Variadic模板構造函數和複製構造函數

#include <string> 
#include <typeindex> 
#include <iostream> 

struct DummyProduction { 
}; 

struct Dep { 
}; 

struct Pro { 
}; 

class ModuleBase { 
}; 

template<typename Production = DummyProduction> 
class Provider { 
public: 
    template<typename... Dependencies> 
    Provider(ModuleBase& module, Dependencies... args) 
    { 
    std::cout << "Provider called!" << std::endl; 
    } 
    Provider(const Provider&) = delete; 
}; 

class TargetController : public ModuleBase, 
    public Provider<Pro>, 
    public Provider<> 
{ 
public: 
    TargetController(); 
private: 
    Dep p; 
}; 

TargetController::TargetController() : 
    ModuleBase(), 
    Provider<Pro>(*this, &p), 
    Provider<>(*this), 
    p() 
{ 
} 

int main() 
{ 
    TargetController x; 
    return 0; 
} 

我用gcc和鏗鏘嘗試。以下是非工作示例的鏈接:link

對於Provider<Pro>(*this, p)正確的構造函數被調用。但對於第二個示例Provider<>(*this),編譯器會嘗試調用複製構造函數。

從我從Overload resolution頁面瞭解的內容中,匹配表達式的所有函數應該進入候選函數集。但是,可變參數不在沒有依賴關係的提供程序的集合內,或者編譯器選擇複製構造函數,儘管被刪除了。

有沒有辦法避免這種行爲?

+0

這樣的問題讓我謙虛:)。 +1爲 – Makketronix

+1

[OT]:請注意'p'尚未在調用'Provider (* this,p)'中構造。 – Jarod42

+0

@ Jarod42是的,這是對的,我忘記了將代碼簡化爲一個簡單的例子。 – Nagua

回答

2

函數/方法爲deleted的事實不會從重載列表中刪除它。 複製構造函數比模板方法具有更高的優先級(因爲它不是完全匹配)。

至於解決方法,你可以施放此與預期型:

TargetController::TargetController() : 
    ModuleBase(), 
    Provider<Pro>(*this, p), 
    Provider<>(static_cast<ModuleBase&>(*this)) 
{ 
} 

Demo

+0

好吧,太糟糕了,沒有一個選項可以從重載列表中刪除複製構造函數。是的,這是在我的代碼中工作。所以,我認爲我現在必須使用它。謝謝。 – Nagua

0

爲模板的構造從來沒有拷貝構造函數。當你調用base的構造函數並將它傳遞給base(或派生的)時,複製構造函數應該被調用。在這種情況下,模板不是一種選擇。

Provider<>(*this) 

就是這樣的背景。

值得注意的是,我相信VS仍然會犯這個錯誤。在該編譯器中,您必須將其轉換爲&,否則它將調用該模板。

+0

感謝您解釋爲什麼這不起作用。你有沒有可以使用其他構造函數的C++標準的參考? – Nagua