即使不调用它,编译器也会在模板类中实例化该函数

时间:2012-10-06 18:09:06

标签: c++ templates compiler-errors instantiation

我错误地认为template中的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解决这个问题?

3 个答案:

答案 0 :(得分: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; }
};

当然,在AT的情况下,这取决于您希望void的行为。当然,您还可以为A专门化整个void结构。

答案 1 :(得分: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;
};

答案 2 :(得分:3)

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

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

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

将编译,因为您没有使用operator*