隐式模板构造函数被忽略

时间:2015-02-15 16:12:53

标签: c++ templates c++11

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;
}

现在我基本上有两个问题:

  1. StructC(const StructC<SB2, T2>& s)构造函数可以用作复制构造函数(移动构造的StructC(StructC<SB2, T2>&& s)计数相同)

  2. 我怎么能说编译器,用FuncStructB<StructA<1>, 1>来呼叫int是完全可以的,尽管它需要StructA<1>float没有显式调用构造函数? StructC的构造函数完全能够在这些构造函数之间进行转换。

  3. 编辑1:提供了一个无法正确失败的示例。

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

相关问题