根据模板参数选择合适的复制构造函数
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 redeclared
和no 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";
}
};
我知道这是一个最小的例子,但是有什么问题
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 的最佳解决方案
我想 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 redeclared
和no 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";
}
};
我知道这是一个最小的例子,但是有什么问题
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 的最佳解决方案