2013-11-22 3 views
4

кодекса говорит:C++: Как частичной специализации шаблонной функции в классе шаблон

template<typename Group> 
struct Vector3D { 
    Group x, y, z; 
    Vector3D(Group x, Group y, Group z) : x(x), y(y), z(z) { 
    } 
    template<int p> Group Norm() const; 
}; 

template<typename Group> template<int p> 
Group Vector3D<Group>::Norm() const { 
    return pow(pow(x, p) + pow(y, p) + pow(z, p), (1.0/p)); 
} 

/* 
template<typename Group> template<> 
Group Vector3D<Group>::Norm<2>() const { 
    return sqrt(x * x + y * y + z * z); 
}*/ 

Закомментированный блок не удается скомпилировать в VC11 (vs2012)

Может кто-нибудь помочь, чтобы указать, что это правильный способ частичной специализации функции Norm?

ответ

4

Вы не можете специализировать шаблон участника, не специализируясь на самом классе. Для этого вам нужно будет использовать другой механизм. Например, вы можете использовать шаблон int2type для сопоставления аргумента шаблона типу, который может передаваться как аргумент в набор перегруженных шаблонов. Рассмотрим упрощенно эскиз того, как это можно сделать:

template <int N> struct int2type {}; 

template <int N> void normImpl(int2type<N>*) { 
... 
} 
void normImpl(int2type<2>*) { 
... 
} 
template <int N> void norm() { 
    return normImpl(static_cast<int2type<N>*>(0)); 
} 

Это может быть реализовано внутри класса (кроме того, что int2type хорошая утилита иметь снаружи).

1

Как и в некоторых из этих типов сценариев, другой уровень косвенности помогает ...

#include <iostream> 
#include <cmath> 
using namespace std; 

template <typename Group, int p> 
struct ApplyNorm 
{ 
    static Group apply(Group x, Group y, Group z) 
    { return pow(pow(x, p) + pow(y, p) + pow(z, p), (1.0/p)); } 
}; 

// Here specialize for 2 
template <typename Group> 
struct ApplyNorm<Group, 2> 
{ 
    static Group apply(Group x, Group y, Group z) 
    { 
     std::cout << "spec: " << std::endl; 
     return sqrt(x * x + y * y + z * z); 
    } 
}; 


template<typename Group> 
struct Vector3D { 
    Group x, y, z; 
    Vector3D(Group x, Group y, Group z) : x(x), y(y), z(z) { 
    } 
    template<int p> Group Norm() const; 
}; 

template<typename Group> template<int p> 
Group Vector3D<Group>::Norm() const { 
    return ApplyNorm<Group, p>::apply(x, y, z); // use the helper... 
} 

int main() { 
    // your code goes here 
    Vector3D<double> v(1., 2., 3.); 
    std::cout << v.Norm<1>() << std::endl; 
    std::cout << v.Norm<2>() << std::endl; 
    return 0; 
} 
+0

+1 Не говоря уже в моем ответе, но среди различных альтернатив, пересылая к статический член шаблона класса, который может быть частично специализированным, является еще одним хорошим вариантом –