关于c ++:专业化模板类的模板成员函数?

Specializing a template member function of a template class?

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

1
2
3
4
5
6
7
8
9
10
template <typename T>
class X
{
public:
    template <typename U>
    void Y() {}

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

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

我试过了:

1
2
3
4
5
6
7
8
9
10
11
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都抱怨。

什么是正确的方法?


非常普遍的问题。 解决它的一种方法是通过重载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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>) { }
};


Use a Helper class to remove the class specialization

例子1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
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;                                                                                                                                                                                                                
}