在c++11
项目中,我有一些类似的结构:
#include <type_traits>
template <bool B, class T = void> using disable_if_t = typename std::enable_if<!(B), T>::type;
enum class disable {};
template <int A> struct StructA
{
using sa = StructA<A>;
static constexpr int a = A;
static constexpr int b = 1;
};
template <typename SA, int B> struct StructB
{
using sa = typename SA::sa;
static constexpr int a = sa::a;
static constexpr int b = B;
};
template <typename SB, typename = int> struct disable_first : std::integral_constant<bool, SB::a == 0 && SB::b == 1>
{
};
template <typename> struct disable_second : std::false_type
{
};
template <typename, typename> class StructC;
template <typename SB, typename T2> struct disable_second<StructC<SB, T2>> : std::true_type
{
};
template <typename SB, typename T> struct StructC
{
template <typename T2, disable_if_t<disable_first<SB, T2>{} || disable_second<T2>{}, disable>...> explicit StructC(T2 v) noexcept;
template <typename SB2, typename T2> StructC(const StructC<SB2, T2>& v) noexcept;
template <typename SB2, typename T2> StructC(StructC<SB2, T2>&& v) noexcept;
};
template <typename T, typename T2> void Func(StructC<StructA<1>, T2> b);
int main()
{
StructC<StructB<StructA<1>, 1>, int> x(40);
Func<float>(x);
return 0;
}
现在我基本上有两个问题:
StructC(const StructC<SB2, T2>& s)
构造函数可以用作复制构造函数(移动构造的StructC(StructC<SB2, T2>&& s)
计数相同)
我怎么能说编译器,用Func
和StructB<StructA<1>, 1>
来呼叫int
是完全可以的,尽管它需要StructA<1>
和float
没有显式调用构造函数? StructC
的构造函数完全能够在这些构造函数之间进行转换。
编辑1:提供了一个无法正确失败的示例。
答案 0 :(得分:2)
StructC(const StructC<S1, T1>& s)
构造函数可以用作复制构造函数(移动构造的StructC(StructC<S1, T1>&& s)
计数相同)
复制或移动构造函数不能是模板。 StructC
将具有隐式声明的复制构造函数和隐式声明的移动构造函数。复制或移动对象时,隐式声明的构造函数将使用构造函数模板参与重载解析;如果它们同样好(在您的代码中似乎就是这种情况),则首选隐式声明的非模板构造函数。
请注意,如果“复制/移动”操作的重载决策选择了构造函数模板而不是实际的复制/移动构造函数,则复制省略(包括(命名)返回值优化)cannot be performed。这可能会影响性能。
我怎么能说编译器,用Func调用它是完全可以的
StructA<1, 2, 3>
和float
虽然需要StructB<4, 5>
和double
没有显式调用构造函数?构造函数StructC
完全能够在这些之间进行转换。
您当前的构造函数模板已经定义了从每种StructC
到其他类型StructC
的隐式转换。一旦将默认构造函数添加到StructC
,您的代码should compile。