выбор соответствующего конструктора копирования на основе параметров шаблона
Я хочу выбрать реализацию функции-члена (конструктор копирования) на основе значения аргумента шаблона. Я полагаю, что есть два подхода: 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 << "falsen";
}
template<typename A>
B<A, true>::B(const B<A, true> &b)
{
std::cout << "truen";
}
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 << "truen";
}
template<typename U = typename std::enable_if<!sw, B>::type>
B(const U &b)
{
std::cout << "falsen";
}
};
int main()
{
{
B<int, true> b;
auto bc = b; // cout << true
}
{
B<int, false> b;
auto bc = b; // cout << false
}
}
ошибка компиляции здесь constructor cannot be redeclared
и no type named 'type' in 'std::enable_if<false, B<int, false> >'; 'enable_if' cannot be used to disable this declaration
.
есть ли способ исправить проблемы или иначе выберите соответствующий конструктор копирования на основе параметров шаблона?
3 ответов
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";
}
};
Как сказал @Joachim Pileborg в комментарии, вы не можете специализироваться только на одном члене класса, вы должны специализировать весь класс. Таким образом, ваша частичная специализация будет выглядеть так:
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";
}
};
лучшее решение, которое вы можете получить для SFINAE, было дано @Piotr Skotnicki
Я знаю, что это минимальный пример, но что не так с
B(const B& b) {
if(sw) {
std::cout << "true\n";
} else {
std::cout << "false\n";
}
}