显式实例化......但没有可用的定义[-fpermissive]

时间:2014-03-25 12:59:03

标签: c++ templates static-members

我尝试使用静态数据成员构建模板类,当我尝试编译以下代码时收到此错误消息:

|In instantiation of ‘T<int>& T<int>::t’:|
16|required from here|
16|error: explicit instantiation of ‘T<int>::t’ but no definition available [-fpermissive]|
|In instantiation of ‘T<int>& T<int>::t’:|
16|required from here|
16|error: explicit instantiation of ‘T<int>::t’ but no definition available [-fpermissive]|
||=== Build finished: 2 errors, 4 warnings (0 minutes, 0 seconds) ===|

代码(为了证明问题而提炼出来。)

template <class A>
class T {
private:
    static T&      t;
public:
    T&   getT() {return t;}
 };

T<int>  i;
template T<int>& T<int>::t;

int main()
{
    i.getT();

    return 0;
}

我害怕我不理解&#34;没有定义的含义。&#34;我认为&#34;模板T&amp; T ::吨;&#34;将定义静态数据成员。

我在Linux上使用GCC:

hbarta@cypress:~$ c++ --version
c++ (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

感谢您的帮助!

编辑:静态成员作为参考的声明显然是一个错误,我已经纠正了。

感谢您提供的多种解决方案和建议。我将不得不研究它们并决定哪种方式最合适。

FWIW,我打算做的是重新发明一个单链表。目标是Arduino,资源有限,对代码和RAM大小敏感。否则我会非常乐意使用STL容器。我正在编写一个单链表,静态数据成员将是一个哨兵,指向列表的头部。列表中的最后一个元素指向哨兵。对于第一次迭代,我开始使用继承编写它,但很快发现各种派生类没有通用代码。 (它们在概念上有相似之处但没有转化为实现,例如它们有不同的列表和不同的处理,所以在我看来,继承是一个糟糕的初始选择。)希望这个困难不是模板同样不是一个好的标志选择。

3 个答案:

答案 0 :(得分:1)

您对静态成员的定义是错误的。对于所有T:

,您必须以模板化的方式进行
template <class A> T<A>& T<A>::t = /* ??? */;

或仅作为整数的专业化:

template<> T<int>& T<int>::t = /* ??? */;

后者将为您提供以下问题:使用除int之外的任何其他类型实例化T将要求您定义这些实例化的静态成员。

此外,如果静态成员是引用,则需要将某个对象绑定到其中,由我的片段中的???表示。使静态成员成为T<A>的对象而不是引用将解决该问题。

答案 1 :(得分:1)

我认为之前的答案提供了您真正需要的解决方案。但是,如果您的真实目标是使用显式实例化,则可以按如下方式实现:

template <class A>
class T
{
private:
    static T t;
public:
    T& getT() {return t;}
};

// definition of a static variable
template <class A>
T<A> T<A>::t;

// explicit instantiation of a static variable for template argument `int`
template T<int> T<int>::t;

请注意,在此代码中,T<A>类型的对象用作静态变量,而不是引用

答案 2 :(得分:0)

我建议在类中使用更简单的单例方法,这对模板特别有用:

template <class A>
class T {
public:
    static T& getT() {
        static T t;
        return t;
    }
};

这样您就不需要额外的定义了。这非常方便,因为在许多情况下模板只是标题,并且没有定义的源文件。

否则你应该在你的声明中删除&

template <class A>
class T {
private:
    static T      t;
public:
    T&   getT() {return t;}
 };

T<int>  i;
template<> T<int> T<int>::t;

为了避免链接器错误,您必须为静态变量赋值。

template<> T<int> T<int>::t = T<int>(); // for example