2

我正在尝试制作一个模板函数(在这种情况下,在一个类中作为静态方法),我似乎无法调用我创建的模板规范。换句话说,我希望代码调用我制作的模板规范,但它没有。

class Atomic { 
public:     
    template <typename T>
    static T testAndSet(volatile T &t, T value) 
    {   
        ASSERT(false, "Unsupported type");
        return T();
    };

    template <long> 
    static long testAndSet(volatile long &t, long value )
    {
    #if defined(_PC)
        return InterlockedExchange(&t, value);  
    #else
        return __sync_lock_test_and_set(&t, value);
    #endif  
    };
};

调用代码:

volatile long counter = 0;      
long newValue = 4;
Atomic::testAndSet( counter, newValue);

调用堆栈显示:

sample.exe!Atomic::testAndSet(volatile long & t=0, long value=4)

我也尝试过这种方式,但没有奏效。

template <typename T, typename TT>
static TT testAndSet(T &t, TT value) { ... }

template <volatile long, long> 
static long testAndSet(volatile long &t, long value ) { ... }

或者

template <typename T, typename TT>
static TT testAndSet(T t, TT value) { ... }

template <volatile long &, long> 
static long testAndSet(volatile long &t, long value ) { ... }

同样的事情......所以现在我必须尝试了解正在发生的事情,或者强行进入它。在那之前,我会看 Lavavej 的核心 c++ 视频.. =)

4

2 回答 2

2

您可以明确专门化模板函数,但这不是函数的标准方法。而且你不能像你那样做:你写的是两个模板函数,一个带有类型参数,另一个带有long非类型参数。

// This defines a template function parameted with a long
//  vvvvvvvvvvvvvvv
    template <long> 
    static long testAndSet(volatile long &t, long value )

您需要在调用站点上明确指定要考虑此重载的模板参数,这就是编译器从未采用它的原因。

你需要在这里重载,用这个改变之前的函数(不需要显式的特化):

// Not a template function
    static long testAndSet(volatile long &t, long value)

此外,使用与类相同的语法来特化函数模板:

// Base case
template<typename T>
void function(T value);

// Explicit specialization (just an example)
template<>
void function<int>(int v, int a);

显式特化和简单重载之间存在一些差异,有关更多详细信息,请参阅此 SO 问题

于 2013-07-30T16:18:50.547 回答
1
template <long> 
static long testAndSet(volatile long &t, long value )
{
#if defined(_PC)
    return InterlockedExchange(&t, value);  
#else
    return __sync_lock_test_and_set(&t, value);
#endif  
};

这不是您似乎认为的专业。它是带有(未命名的)非类型模板参数的重载。在重载决议期间永远不会为您所做的调用选择它,因为您需要显式指定参数,例如:testAndSet<42>(counter, newValue);.

你想要的语法是:

template <>  // <---
static long testAndSet<long>(volatile long &t, long value )
{                  // ^^^^^^
    //....
}

但此时您也可以提供正常的过载。

你应该总是更喜欢重载,因为函数模板的特化会让你大吃一惊

于 2013-07-30T16:18:15.570 回答