【问题标题】:Compiler instantiates the function in a template class even without invoking it编译器在模板类中实例化函数,即使没有调用它
【发布时间】:2012-10-06 18:09:05
【问题描述】:

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

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&lt;void&gt; 时,编译器错误输出为:

error: forming reference to void

我尝试在模板之外专门为void 提供如下功能:

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

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

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

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

【问题讨论】:

  • 是的,您正在调用模板。另外,你调用它的方式,你甚至创建了一个变量,所以有对构造函数和析构函数的调用,这比仅仅提到类型更“调用”。
  • 抱歉,你想做什么?
  • @Christian:类模板的成员函数除非使用,否则不会实例化。
  • @KirilKirov,由于实际代码很复杂,因此无法解释。所以我只是演示了一个工作示例。简而言之,我可以说我创建了一个智能指针A,它应该可以从任何类型转换为A&lt;void&gt;,并且有后续要求。

标签: c++ templates compiler-errors instantiation


【解决方案1】:

怎么样

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; }
};

当然,如果Tvoid,这取决于您希望A 的行为。当然,您也可以将整个 A 结构体专门化为 void

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 此外,为A&lt;void&gt;::operator* 提供显式特化的尝试失败,因为它与主模板中的声明不匹配:返回类型不同。 (这当然是 OP 的意图,但不允许。)
    【解决方案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;
    };
    

    【讨论】:

    • 仅从您的答案一瞥,我发现我需要更改返回类型,并且我想出了与@DyP 的答案完全匹配的解决方案。仍然对此 +1。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-16
    • 1970-01-01
    • 2013-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多