我有一个类,允许创建一个包含任何类型或类的向量。但是,我想为数字类型添加其他功能。
template <>
class Vec<double> : public VecBase<double>
{
// == METHODS ==
public:
// -- Constructors & Destructors --
explicit Vec(const unsigned long long t_size);
virtual ~Vec();
// -- Operators --
friend Vec<double> operator+(const Vec<double>&, const double);
// -- Methods --
double sum();
... etc.
我已经部分专门化了类模板,允许重载数学运算符以进行双重特化。我现在也希望将这个特化扩展到int,但是不是复制用int替换double的特化,有没有办法将它添加到特化列表中?
也就是说,有没有办法允许:
template<>
class Vec<double (or) int>
干杯!
答案 0 :(得分:1)
我想您可以使用布尔默认值,例如以下示例中的foo
结构
#include <iostream>
template <typename>
struct isSpecialType
{ static constexpr bool value { false }; };
template <>
struct isSpecialType<int>
{ static constexpr bool value { true }; };
template <>
struct isSpecialType<double>
{ static constexpr bool value { true }; };
template <typename T, bool = isSpecialType<T>::value>
struct foo;
template <typename T>
struct foo<T, true>
{ static constexpr bool value { true }; };
template <typename T>
struct foo<T, false>
{ static constexpr bool value { false }; };
int main()
{
std::cout << "- void value: " << foo<void>::value << std::endl;
std::cout << "- bool value: " << foo<bool>::value << std::endl;
std::cout << "- int value: " << foo<int>::value << std::endl;
std::cout << "- double value: " << foo<double>::value << std::endl;
}
我们的想法是定义一种类型特征(isSpecialType
)来选择所选类型(在您的示例中为int
和double
),其中booleand值为{{1在通用实现中,以及专业化中的false
。
true
接下来,您必须使用template <typename>
struct isSpecialType
{ static constexpr bool value { false }; };
template <>
struct isSpecialType<int>
{ static constexpr bool value { true }; };
template <>
struct isSpecialType<double>
{ static constexpr bool value { true }; };
模板值foo
默认值
class Vec
结构(bool
)
isSpecialType<T>::value
最后,您必须实现两个部分专用的template <typename T, bool = isSpecialType<T>::value>
struct foo;
版本:第一个具有布尔foo
值
true
对应于template <typename T>
struct foo<T, true>
{ static constexpr bool value { true }; };
的专业版;具有Vec
布尔值
false
对应于template <typename T>
struct foo<T, false>
{ static constexpr bool value { false }; };
。
另一点:我的例子是C ++ 11或更新的代码;如果你想要一个C ++ 98版本,你只需要将Vec
值定义为bool
(而不是const
)并使用C ++ 98样式初始化它们;我的意思是
constexpr
而不是
static bool const bool value = true;
答案 1 :(得分:1)
确实有,但你可能已经在http://en.cppreference.com/w/cpp/numeric/valarray
中找到了查看std :: enable_if和std :: is_integral以及std :: is_floating_point。 (copied from cplusplus.com)
// enable_if example: two ways of using enable_if
#include <iostream>
#include <type_traits>
// 1. the return type (bool) is only valid if T is an integral type:
template <class T>
typename std::enable_if<std::is_integral<T>::value,bool>::type
is_odd (T i) {return bool(i%2);}
// 2. the second template argument is only valid if T is an integral type:
template < class T,
class = typename std::enable_if<std::is_integral<T>::value>::type>
bool is_even (T i) {return !bool(i%2);}
int main() {
short int i = 1; // code does not compile if type of i is not integral
std::cout << std::boolalpha;
std::cout << "i is odd: " << is_odd(i) << std::endl;
std::cout << "i is even: " << is_even(i) << std::endl;
return 0;
}
答案 2 :(得分:0)
我对@ max66也有相同的想法,但是您可以使用一个辅助函数使此操作更加容易。
#include <iostream>
#include <type_traits>
// helper
template <typename ...Ts>
struct allowed_types
{
template <typename T>
using check = std::disjunction<std::is_same<T, Ts>...>;
template <typename T>
inline static constexpr bool check_v = check<T>::value;
};
// usage
template <typename T, bool = allowed_types<double, float>::check_v<T>>
struct foo;
template <typename T>
struct foo<T, true> // for double and float
{
inline static constexpr size_t value = 1;
};
template <typename T>
struct foo<T, false> // for other types
{
inline static constexpr size_t value = 2;
};
int main()
{
std::cout << foo<float>::value << '\n'; // 1
std::cout << foo<double>::value << '\n'; // 1
std::cout << foo<int>::value << '\n'; // 2
std::cout << foo<char>::value << '\n'; // 2
}
只需输入您需要的任何类型的集即可。 例如:
template <typename T, bool = allowed_types<char, int, std::vector<int>>::check_v<T>>
编辑:
如果您需要将专业划分为两个以上的组,则需要使用enable_if方法。
有了上面的帮助,它可以这样写:
// default, for any type
template <typename T, typename = void>
struct foo
{
inline static constexpr size_t value = 1;
};
// for double and float
template <typename T>
struct foo<T, std::enable_if_t<allowed_types<double, float>::check_v<T>>>
{
inline static constexpr size_t value = 2;
};
// for int and char
template <typename T>
struct foo<T, std::enable_if_t<allowed_types<int, char>::check_v<T>>>
{
inline static constexpr size_t value = 3;
};
int main()
{
std::cout << foo<bool>::value << '\n'; // 1
std::cout << foo<double>::value << '\n'; // 2
std::cout << foo<float>::value << '\n'; // 2
std::cout << foo<int>::value << '\n'; // 3
std::cout << foo<char>::value << '\n'; // 3
}