Specializing a template member function of a templ

2020-07-16 12:07发布

I have a template class that has a template member function that needs to be specialized, as in:

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

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

Altough VC handles this correctly, apperantly this isn't standard and GCC complains: explicit specialization in non-namespace scope 'class X<T>'

I tried:

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

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

But this causes both VC and GCC to complain.

What's the right way to do this?

2条回答
甜甜的少女心
2楼-- · 2020-07-16 12:40

Use a Helper class to remove the class specialization

Example 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>());
}

Example 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;                                                                                                                                                                                                                 
}                                                                                                                             
查看更多
够拽才男人
3楼-- · 2020-07-16 12:51

Very common problem. One way to solve it is through overloading

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>) { }
};
查看更多
登录 后发表回答