C ++ - 专门用于模板类的成员函数

时间:2014-10-08 15:30:50

标签: c++ templates template-specialization

我有一个表示数学向量的类模板:

template<class Value_T, unsigned int N>
class VectorT
{
public:

    void Normalize()
    {
        // normalize only double/float vectors here
    }

private:
    // elements in the vector
    value_type elements[N];     

    // the number of elements
    static const size_type size = N;
};

我想对整数类型的向量进行特殊处理,因为在这种类型上不能进行向量归一化。所以我需要一个单独的(可能是专门化的)Normalize方法,它依赖于VectorT类模板的模板参数Value_T。

我尝试过以不同的方式使用模板专业化,但没有让它起作用。我是否必须将N​​ormalize功能本身作为模板功能?目前它只是普通的成员方法。

4 个答案:

答案 0 :(得分:3)

您可以使用标记调度技术解决此问题:

#include <iostream>
#include <type_traits>

template<class Value_T, unsigned int N>
class VectorT
{
public:
    void Normalize()
    {
        using tag = std::integral_constant<bool
                                         , std::is_same<Value_T, double>::value
                                           || std::is_same<Value_T, float>::value>;  

        // normalize only double/float vectors here
        Normalize(tag());
    }

private:
    void Normalize(std::true_type)
    {
        std::cout << "Normalizing" << std::endl;
    }

    void Normalize(std::false_type)
    {
        std::cout << "Not normalizing" << std::endl;
    }

    // elements in the vector
    Value_T elements[N];     

    // the number of elements
    static const std::size_t size = N;
};

DEMO

答案 1 :(得分:1)

您似乎希望禁止Normalize以外的其他类型而不是浮点数,因此您可以使用static_assert来获得良好的错误消息:

template<class Value_T, unsigned int N>
class VectorT
{
public:

    void Normalize()
    {
        static_assert(std::is_floating_point<Value_T>::value, "Normalize available only for floating point");
        // normalize only double/float vectors here
    }

// Other stuff

};

答案 2 :(得分:1)

您也可以使用std :: enable_if&lt;&gt;

#include <iostream>
#include <type_traits>

template<class Value_T>
class VectorT
{
public:
    template<class T = Value_T>
    typename std::enable_if<std::is_integral<T>::value, void>::type
    Normalize()
    {
        std::cout << "Not normalizing" << std::endl;
    }

    template<class T = Value_T>
    typename std::enable_if<!std::is_integral<T>::value, void>::type
    Normalize()
    {
         std::cout << "Normalizing" << std::endl;
    }
};

int main()
{
    VectorT<int> vint;
    VectorT<double> vdouble;

    vint.Normalize();
    vdouble.Normalize();

    return 0;
}

DEMO

答案 3 :(得分:1)

是的,您可以独立地专门化模板类的特定成员函数。但是,功能模板(包括成员函数模板)不允许部分特化。功能模板仅支持显式特化。您案例中的明确专业化,如下所示

// Header file

template<class Value_T, unsigned int N>
class VectorT
{
public:

  void Normalize()
  {
      // normalize only double/float vectors here
  }
  ...
};

// Declare an explicit specialization for <int, 5>
template <> void VectorT<int, 5>::Normalize();

然后

// Implementation file

// Define the explicit specialization for <int, 5>
template <> void VectorT<int, 5>::Normalize()
{
   ...
}

然而,显然初始化并不是你需要的,显然,因为你想要修复&#34;仅限类型并保持大小灵活,即您需要部分专业化。这可以使用C ++ 11的std::enable_if功能(如其他答案中所示)以及C ++ 98的一些基本技巧来完成。

当然,如果你的类相对轻量级,即除Normalize之外它没有太多通用代码,你可以简单地部分专门化整个类。这需要更多的打字。