HankB
HankB

Reputation: 332

explicit instantiation ... but no definition available [-fpermissive]

I'm trying to construct a template class with a static data member and I get this error message when I try to compile the following code:

|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) ===|

code (distilled to the demonstrate the problem.)

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

I'm afraid I do not understand what is meant by "no definition available." I thought that "template T& T::t;" would define the static data member.

I'm using GCC on Linux:

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.

Thanks for any help!

Edit: The declaration of the static member as a reference was clearly an error and I have corrected that.

Thanks for the several solutions and suggestions for this. I will have to study them and decide which is most appropriate.

FWIW, what I am planning to do is reinvent a singly linked list. The target is an Arduino and with limited resources will be sensitive to code and RAM size. Otherwise I would be more than happy to use STL containers. I am coding a singly linked list and the static data member will be a sentinel, pointing to the head of the list. Last element on the list points to the sentinel. For the first iteration, I started writing this using inheritance but soon found that there was no common code for the various derived classes. (They share similarity in concept but that has not translated to implementation, e.g they had distinct lists and distinct processing so it seemed to me that inheritance was a poor initial choice.) Hopefully this difficulty is not a sign that templates are likewise not a good choice.

Upvotes: 1

Views: 8154

Answers (3)

Danvil
Danvil

Reputation: 22991

I would suggest a simpler method for singletons in a class which is especially useful for templates:

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

This way you do not need an extra definition. This is very convenient, as in many cases templates are header only and do not have a source file for definitions.

Otherwise you should drop the & in your declaration:

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

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

And to avoid a linker error, you have to assign something to the static variable.

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

Upvotes: 0

Constructor
Constructor

Reputation: 7473

I think that previous answers provide the solution that you really need. But if your real aim was to use explicit instantiation it can be achieved as follows:

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;

Note that in this code an object of type T<A> is used as a static variable instead of a reference to it.

Upvotes: 1

Arne Mertz
Arne Mertz

Reputation: 24596

Your definition of the static member is wrong. You either have to do it the templated way, for all T:

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

Or as a specialization only for ints:

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

The latter will leave you with the issue that instantiating T with any other type than int will require you to define the static member of those instantiations as well.

In addition, if the static member is a reference, you will need to have some object to bind it to, denoted by the ??? in my snippets. Making the static member an object of T<A> instead of a reference will solve that problem.

Upvotes: 2

Related Questions