专门化模板类的模板成员函数?

时间:2010-06-14 19:19:04

标签: c++ templates template-specialization

我有一个模板类,它具有需要专门化的模板成员函数,如:

template <typename T>
class X
{
public:
    template <typename U>
    void Y() {}

    template <>
    void Y<int>() {}
};

Altough VC正确处理此问题,显然这不是标准问题,GCC抱怨:explicit specialization in non-namespace scope 'class X<T>'

我试过了:

template <typename T>
class X
{
public:
    template <typename U>
    void Y() {}
};

template <typename T>
// Also tried `template<>` here
void X<T>::Y<int>() {}

但这会导致VC和GCC抱怨。

这样做的正确方法是什么?

2 个答案:

答案 0 :(得分:8)

很常见的问题。解决问题的一种方法是通过重载

template <typename T>
struct type2type { typedef T type; };

template <typename T>
class X
{
public:
    template <typename U>
    void Y() { Y(type2type<U>()); }

private:
    template<typename U>
    void Y(type2type<U>) { }

    void Y(type2type<int>) { }
};

答案 1 :(得分:0)

  

使用Helper类删除类专门化

示例1

namespace {
/* Make this work
template <typename T>
class X
{
public:
    template <typename U>
    void Y() {}

    template <>
    void Y<int>() {}
};
*/

template <typename  K>
struct IntegerHelper {
    static bool isInteger() { return false; }
};

template <>
inline bool IntegerHelper<int>::isInteger() {
    return true;
}

template <typename T>
class TestX {

public:
    template <typename K>
    static bool isInteger() {
        return IntegerHelper<K>::isInteger();
    }
};

}

TEST(TestTemplateMethodSpecialization, Basic) {
    EXPECT_TRUE(TestX<double>::isInteger<int>());
    EXPECT_FALSE(TestX<double>::isInteger<double>());
}

示例2

enum class Side {                                                                                                                                                                                                                                                                                     
   BUY = 0,                                                                                                                                                                                                                                                                                           
   SELL                                                                                                                                                                                                                                                                                               
};                                                                                                                                                                                                                                                                                                    

using PriceType = int64_t;                                                                                                                                                                                                                                                                            

class BookHelper {                                                                                                                                                                                                                                                                                    

public:                                                                                                                                                                                                                                                                                               

BookHelper(                                                                                                                                                                                                                                                                                           
   PriceType insideBuyPrice,                                                                                                                                                                                                                                                                          
   PriceType insideSellPrice)                                                                                                                                                                                                                                                                         
:                                                                                                                                                                                                                                                                                                     
   insideBuyPrice_{insideBuyPrice},                                                                                                                                                                                                                                                                   
   insideSellPrice_{insideSellPrice}                                                                                                                                                                                                                                                                  
{ }                                                                                                                                                                                                                                                                                                   

template <Side SideV>                                                                                                                                                                                                                                                                                 
PriceType insidePrice() const;                                                                                                                                                                                                                                                                        

template <Side SideV>                                                                                                                                                                                                                                                                                 
void insidePrice(PriceType price);                                                                                                                                                                                                                                                                    

private:                                                                                                                                                                                                                                                                                              
   PriceType insideBuyPrice_;                                                                                                                                                                                                                                                                         
   PriceType insideSellPrice_;                                                                                                                                                                                                                                                                        

};                                                                                                                                                                                                                                                                                                    

template <>                                                                                                                                                                                                                                                                                           
inline void BookHelper::insidePrice<Side::BUY>(PriceType price) {                                                                                                                                                                                                                                     
   insideBuyPrice_ = price;                                                                                                                                                                                                                                                                           
}                                                                                                                                                                                                                                                                                                     

template <>                                                                                                                                                                                                                                                                                           
inline void BookHelper::insidePrice<Side::SELL>(PriceType price) {                                                                                                                                                                                                                                    
   insideSellPrice_ = price;                                                                                                                                                                                                                                                                          
}                                                                                                                                                                                                                                                                                                     

template <>                                                                                                                                                                                                                                                                                           
inline PriceType BookHelper::insidePrice<Side::BUY>() const {                                                                                                                                                                                                                                         
   return insideBuyPrice_;                                                                                                                                                                                                                                                                            
}                                                                                                                                                                                                                                                                                                     
                                                                                                                                                                                                                                                                                                      template <>                                                                                                                                                                                                                                                                                           
inline PriceType BookHelper::insidePrice<Side::SELL>() const {                                                                                                                                                                                                                                        
   return insideSellPrice_;                                                                                                                                                                                                                                                                           
}                                                                                                                                                                                                                                                                                                     

template <typename BookT>                                                                                                                                                                                                                                                                             
class Book {                                                                                                                                                                                                                                                                                          

public:                                                                                                                                                                                                                                                                                               
   Book();                                                                                                                                                                                                                                                                                            

   template <Side SideV>                                                                                                                                                                                                                                                                              
   PriceType insidePrice() const;                                                                                                                                                                                                                                                                     

   template <Side SideV>                                                                                                                                                                                                                                                                              
   void insidePrice(PriceType price);                                                                                                                                                                                                                                                                 

private:                                                                                                                                                                                                                                                                                              
   std::unique_ptr<BookHelper> helper_;                                                                                                                                                                                                                                                               

};                                                                                                                                                                                                                                                                                                    

template<typename BookT>                                                                                                                                                                                                                                                                              
Book<BookT>::Book() :                                                                                                                                                                                                                                                                                 
   helper_{new BookHelper{std::numeric_limits<PriceType>::min(), std::numeric_limits<PriceType>::max()}}                                                                                                                                                                                              
{}                                                                                                                                                                                                                                                                                                    

template <typename BookT>                                                                                                                                                                                                                                                                             
template <Side SideV>                                                                                                                                                                                                                                                                                 
PriceType Book<BookT>::insidePrice() const {                                                                                                                                                                                                                                                          
   return helper_->insidePrice<SideV>();                                                                                                                                                                                                                                                              
}                                                                                                                                                                                                                                                                                                     

template <typename BookT>                                                                                                                                                                                                                                                                             
template <Side SideV>                                                                                                                                                                                                                                                                                 
void Book<BookT>::insidePrice(PriceType price) {                                                                                                                                                                                                                                                      
   helper_->insidePrice<SideV>(price);                                                                                                                                                                                                                                                                
}                                                                                                                                                                                                                                                                                                     

class TestBook { };                                                                                                                                                                                                                                                                                   

int main() {                                                                                                                                                                                                                                                                                          
   Book<TestBook> test;                                                                                                                                                                                                                                                                               
   test.insidePrice<Side::SELL>(1230046);                                                                                                                                                                                                                                                             
   test.insidePrice<Side::BUY>(1230045);                                                                                                                                                                                                                                                              

   std::cout << " inside SELL price : " << test.insidePrice<Side::SELL>() << std::endl;                                                                                                                                                                                                               
   std::cout << " inside BUY price : " << test.insidePrice<Side::BUY>() << std::endl;                                                                                                                                                                                                                 
}