根据模板参数选择合适的复制构造函数

selecting appropriate copy-constructor based on template parameters

我想 select 基于模板参数值实现成员函数(复制构造函数)。我想有两种方法:SFINAE 和模板偏特化。

最后一个应该是这样的:

#include <iostream>

template<typename A, bool sw>
struct B
{
    B() {}
    B(const B &b);
};

template<typename A>
B<A, false>::B(const B<A, false> &b)
{
    std::cout << "false\n";
}

template<typename A>
B<A, true>::B(const B<A, true> &b)
{
    std::cout << "true\n";
}

int main()
{
}

它没有编译:nested name specifier 'B<A, false>::' for declaration does not refer into a class, class template or class template partial specialization

SFINAE 方法也失败了:

#include <type_traits>
#include <iostream>

template<typename A, bool sw>
struct B
{
    B() {}

    template<typename U = typename std::enable_if<sw, B>::type>
    B(const U &b)
    {
        std::cout << "true\n";
    }

    template<typename U = typename std::enable_if<!sw, B>::type>
    B(const U &b)
    {
        std::cout << "false\n";
    }
};

int main()
{
    {
        B<int, true> b;
        auto bc = b; // cout << true
    }
    {
        B<int, false> b;
        auto bc = b; // cout << false
    }
}

这里的编译错误是constructor cannot be redeclaredno type named 'type' in 'std::enable_if<false, B<int, false> >'; 'enable_if' cannot be used to disable this declaration.

有什么方法可以解决这些问题,或者 select 基于模板参数的适当的复制构造函数?

template <typename A, bool sw>
struct B
{
    B() = default;

    B(const B& b) : B(b, std::integral_constant<bool, sw>{}) {}

private:
    B(const B& b, std::true_type)
    {
        std::cout << "true\n";
    }

    B(const B& b, std::false_type)
    {
        std::cout << "false\n";
    }
};

DEMO

我知道这是一个最小的例子,但是有什么问题

B(const B& b) {
  if(sw) {
    std::cout << "true\n";
  } else {
    std::cout << "false\n";
  }
}

正如@Joachim Pileborg 在评论中所说,你不能只专注于 class 的一个成员,你必须专注于整个 class。所以你的部分专业化看起来像这样:

template<typename A, bool sw>
struct B
{
    B() {}
    B(const B &b);
};

//Specialize when sw is false
template<typename A>
struct B<A, false>
{
     //The constructor in the specialized struct print false
     B(const B &b)
     {
        std::cout << "false\n";
     }
};

//Specialize when sw is true
template<typename A>
struct B<A, true>
{
    //The constructor in the specialized struct print true
    B(const B &b)
    {
        std::cout << "true\n";
    }
};

@Piotr Skotnicki 给出了 SFINAE 的最佳解决方案