多种类型

时间:2017-04-23 23:04:32

标签: c++ templates operator-overloading template-specialization partial-specialization

我有一个类,允许创建一个包含任何类型或类的向量。但是,我想为数字类型添加其他功能。

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>

干杯!

3 个答案:

答案 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)来选择所选类型(在您的示例中为intdouble),其中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
}