2013-02-04 59 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演示。