例如,我有
#include <iostream>
template <typename T>
struct Base {};
template <>
struct Base<std::string> {
static const int value = true;
};
template <>
struct Base<std::string &> {
static const int value = true;
};
int main() {
bool a = Base<std::string>::value;
bool b = Base<std::string &>::value;
std::cout << a << b << std::endl;
}
请注意,我有两个相同的专业,并且希望将其简化为一个。我知道有两种我不愿意使用的解决方案。
(1)删除呼叫站点上的引用,以便只需要一种专业化。
(2)创建一个基类,并从中继承引用和无引用版本。
是否存在第三个选择,即专业化是对引用类型和非引用类型的通用?
需要C ++ 11解决方案。
答案 0 :(得分:3)
1)看起来不错:
template <typename T>
struct BaseImpl {};
template <>
struct BaseImpl<std::string> {
static const int value = true;
};
template <typename T>
using Base = BaseImpl<typename std::remove_reference<T>::type>;
2)似乎更详细
template <typename T>
struct BaseImpl {};
template <>
struct BaseImpl<std::string> {
static const int value = true;
};
template <typename T>
struct Base : BaseImpl<T> {}; // or directly BaseImpl<std::remove_reference_t<T>>
template <typename T>
struct Base<T&> : BaseImpl<T> {};
3)与2)相似,冗长一些,但可能更棘手
template <typename T>
struct Base : Base<T&> {};
template <typename T>
struct Base<T&> {};
template <>
struct Base : Base<std::string> {
static const int value = true;
};
1)似乎更易读,易于实现。
答案 1 :(得分:2)
enable_if有点繁琐,但我认为没有更好的方法。
#include <iostream>
#include <type_traits>
template <typename T, typename Enable = void>
struct Base {};
template <typename T>
struct Base<
T,
typename std::enable_if<
std::is_same<typename std::decay<T>::type, std::string>::value
>::type
>
{
static const int value = true;
};
int main() {
bool a = Base<std::string>::value;
bool b = Base<std::string &>::value;
std::cout << a << b << std::endl;
}
答案 2 :(得分:2)
您可以在SFINAE上下文中执行检查:
// type trait to remove the lvalue-reference
template< class T > struct remove_lvalue_reference {typedef T type;};
template< class T > struct remove_lvalue_reference<T&> {typedef T type;};
template <typename T>
using remove_lvalue_reference_t = typename remove_lvalue_reference<T>::type;
template <typename T, typename = void>
struct Base {};
// valid when T is std::string and std::string&
template <typename T>
struct Base<T, typename std::enable_if<std::is_same<std::string, remove_lvalue_reference_t<T>>::value>::type> {
static const int value = true;
};