构造函数中的模板冲突 [英] Template collision in constructors
问题描述
我有一个定义如下的结构:
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;
sample1(b);
A sample2(3); //例如,B有一个B(int)构造函数。
}
这不能正常工作,因为 A(b)
尝试使用第二个构造函数(非常量引用是首选选项,第一个构造函数是常量引用),但 B
没有任何 B(A&)
。
此外,我想添加一个 move
B的构造函数:
struct A:public B,public C
{
A(const B& b):B(b),C()
{}
A(B& b) :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& Args>
A(Args& ... args):B(),C(std :: forward< Args>(args)...)
{}
};问题:如果第一个版本导致冲突,最后一个版本(我的最终目的)清楚地表明它是一个新的版本。不工作也。 解决方案一个可能的解决方案是使用 std :: enable_if
cppreference.com/w/cpp/types/is_convertiblerel =nofollow> std :: 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&
A(T& t){std :: cout<< A(T&)\\\
; }
template< class ... TArgs>
A(TArgs& ... targs){std :: cout< A(TArgs&&)\\\
; }
};
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 上的演示。
I have a struct defined as follows:
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.
}
And this doesn't work fine, because, A(b)
tries use the second constructor (the non-constant reference is the preferred option, and the first constructor is a constant reference), but B
hasn't any B(A&)
.
And moreover, I want to add a move
constructor for 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)...)
{}
};
Now, the last step is to fusion the first two constructors:
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)...)
{}
};
Question: if the first version causes collision, the last version (my final purpose) its clear that it doesn't work also. How could I achieve this goal?
解决方案 A possible solution would be use std::enable_if
with std::is_convertible
to only include the first constructor if the type of argument b
is convertible to B
:
template <
class fw_B,
class = typename std::enable_if<std::is_convertible<fw_B, B>::value, T>::type>
A(fw_B&& b)
For example:
#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;
}
Output:
A(T&&)
A(T&&)
A(TArgs&&)
See demo at http://ideone.com/xJEjic .
这篇关于构造函数中的模板冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!