3

I have a template class with a structure about as follows:

foobar.h:

class Bar
{
    Bar(float f);
};

template<typename T>
class Foo
{
    Foo(const Bar&);
    ...
    static const Foo mkFooConst;
};

typedef Foo<float> MathFoo;

foobar.c:

template<> const MathFoo MathFoo::mkFooConst(Bar(0.815));

Now this seems to be the commonly recommended way to initialize a static member of a template class that can't be initialized trivially in its declaration. And with both VS 2015 and g++ it seems to work nicely.

However, clang doesn't agree, and issues a warning when the class is ultimately used:

warning: instantiation of variable 'Foo<float>::mkFooConst' required
here, but no definition is available [-Wundefined-var-template]
...
note: add an explicit instantiation declaration to suppress this
warning if 'Foo<float>::mkFooConst' is explicitly instantiated in
another translation unit.

It is my understanding that this means I should add the following code to the header file:

extern template class MathFoo<float>;

and presumably the following to the cpp file:

template class MathFoo<float>;

but no matter where I put it, all this gives me is an outright error instead of the warning - either 'explicit specialization after instantiation' or 'explicit specialization after instantiation' 'explicit instantiation after specialization'.

I also tried to add an explicit instantiation declaration for just the member, but that didn't work either.

Any ideas?

C++17 is not an option for me, unfortunately; the code must be compatible with C++11.

Christoph Lipka
  • 652
  • 4
  • 15
  • 1
    @Swordfish: That doesn't look like a duplicate to me, at all. The OP here is using one of the technical solutions to that question. – Cheers and hth. - Alf Sep 07 '18 at 16:31
  • 1
    Reopened since the hoped-for dupe was not. – Cheers and hth. - Alf Sep 07 '18 at 16:34
  • Do you have to support other template type arguments than `float`, with possibly different values? Because if not, then as a practical workaround you can just provide a templated general definition in the header. That still leaves the clang question, though. – Cheers and hth. - Alf Sep 07 '18 at 16:36
  • 3
    I can't reproduce the problem. Please, edit your question and add a [mcve](https://stackoverflow.com/help/mcve) – Ripi2 Sep 07 '18 at 16:47
  • _"either 'explicit specialization after instantiation' or 'explicit specialization after instantiation'."_ Those are the same. Maybe you pasted the same one twice by accident? – Max Langhof Sep 07 '18 at 16:59
  • @Ripi2: Can reproduce [here](http://coliru.stacked-crooked.com/a/2b1d83069c23dfd8). – Jarod42 Sep 07 '18 at 19:35
  • Possible duplicate of [Static member initialization in a class template](https://stackoverflow.com/q/3229883/608639), [Static member initialization in a template class](https://stackoverflow.com/q/48268452/608639), [C++ Static member initialization (template fun inside)](https://stackoverflow.com/q/1819131/608639), etc. – jww Sep 08 '18 at 01:53
  • @jww: I disagree with duplicates. – Jarod42 Sep 10 '18 at 08:14

1 Answers1

0

You have to put:

template<> const MathFoo MathFoo::mkFooConst;
// Declaration only, mkFooConst{} would be a definition.

Demo with multiple file

No warning with clang

Jarod42
  • 203,559
  • 14
  • 181
  • 302