2

我错误地认为templatea 中的函数class只有在被调用时才会被实例化。请看下面的简单代码:

template<typename T>
struct A
{
  T *p; 
  T& operator * () { return *p; }
};

int main ()
{
  A<int> ai;   // ok
  int i = *ai;  // works fine
  A<void> av;  // compiler complains even "*av" is not called
}

就在声明时A<void>,编译器错误为:

error: forming reference to void

我尝试专门针对void模板外部的功能,如下所示:

template<>
void A<void>::operator * () {}

但它没有帮助并给出错误:

error: no member function ‘operator*’ declared in ‘A<void>’

有没有办法用 C++03 解决这个问题?

4

3 回答 3

5

关于什么

template < typename T >
struct ReferenceOrVoid
{ typedef T& Value; };

template < >
struct ReferenceOrVoid < void >
{ typedef void Value; };

template<typename T>
struct A
{
    T *p; 
    typename ReferenceOrVoid < T > :: Value
    operator * () { return *p; }
};

当然,这取决于您A在. 当然,您也可以将整个结构专门化为。TvoidAvoid

于 2012-10-06T18:21:25.417 回答
3

我认为如果你给函数一个不同的返回类型就足够了void

template <typename T>
struct is _void {
    enum { value = false };
};
template <>
struct is_void<> {
    enum { value = true };
};

struct A {
    ...
    typename enable_if<!is_void<T::value>, T&>::type
    operator*() {
        ...
    }
};

由于仍然可以检查签名,因此您可能需要使用条件类型,例如,void在使用 实例化时进行void

template <bool, typename T1, typename>
struct conditional {
    typedef T1 type;
};
template <typename T1, typename T2>
struct conditional<false, T1, T2> {
    typedef T2 type;
};
于 2012-10-06T18:19:34.050 回答
3

函数的签名将被实例化,函数的主体不会。T在整个类定义中被替换,无论您是否使用该函数。请注意:

template<typename T>
struct A
{
  T *p; 
  T *operator * () { return p->aklsdjlkasjd(); }
};

int main ()
{
  A<void> av;  
}

将编译,因为您不使用operator*.

于 2012-10-06T18:20:05.537 回答