2013-02-04 63 views
2

我有一個結構定義如下:模板碰撞

struct A : public B, public C 
{ 
    A(const B& b) : B(b), C() 
    {} 

    template<typename... Args> 
    A(Args&&... args) : B(), C(std::forward<Args>(args)...) 
    {} 
}; 

int main() 
{ 
    B b; 

    A sample1(b); 
    A sample2(3); // For example, B has a B(int) constructor. 
} 

而且這不正常工作,因爲,A(b)嘗試使用第二構造(非恆定的基準是優選的選項,並第一個構造函數是一個常量引用),但B還沒有任何B(A&)

而且,我想補充一個move構造方法B:

struct A : public B, public C 
{ 
    A(const B& b) : B(b), C() 
    {} 

    A(B&& b) : B(std::move(b)), C() 
    {} 

    template<typename... Args> 
    A(Args&&... args) : B(), C(std::forward<Args>(args)...) 
    {} 
}; 

現在,最後一步是融合前兩個構造函數:

struct A : public B, public C 
{ 
    template<typename fw_B> 
    A(fw_B&& b) : B(std::forward<fw_B>(b)), C() 
    {} 

    template<typename... Args> 
    A(Args&&... args) : B(), C(std::forward<Args>(args)...) 
    {} 
}; 

問:如果第一個版本導致碰撞,最後的版本(我的最終目的)明確表示它也不起作用。我怎麼能實現這個目標?

+0

您的代碼中存在一個錯誤。 'A(b);'相當於'A b;',所以它不*傳遞'b'給任何構造函數。 –

+0

對不起,你說得對,我寫了這個代碼「到位」。非常感謝 :) –

回答

2

一種可能的解決方案將是使用std::enable_ifstd::is_convertible僅包括第一構造函數,如果參數b的類型可以轉換爲B

template < 
    class fw_B, 
    class = typename std::enable_if<std::is_convertible<fw_B, B>::value, T>::type> 
A(fw_B&& b) 

例如:

#include <iostream> 
#include <type_traits> 

struct B 
{ 
    B() {} 
    B(int) {} 
}; 

struct C {}; 

struct A : B, C 
{ 
    template < 
     class T, 
     class = typename std::enable_if<std::is_convertible<T, B>::value, T>::type> 
    A(T&& t) { std::cout << "A(T&&)\n"; } 

    template <class... TArgs> 
    A(TArgs&&... targs) { std::cout << "A(TArgs&&)\n"; } 
}; 

int main() 
{ 
    B b; 

    A a1(b); 
    A a2(4); 
    A a3("hello"); 

    return 0; 
} 

輸出:

 
A(T&&) 
A(T&&) 
A(TArgs&&) 

參見http://ideone.com/xJEjic演示。