jeudi 25 janvier 2018

explicit instantiation declaration of template class field

I have such test.hpp:

#include <cstring>
#include <cassert>
#include <map>

template <typename T, typename Tag> struct Boo {
  using ElementType = T;
  static const char name[];
};

struct CFG_ELM_NAME__Pref1 {};
using Pref1 = Boo<int, CFG_ELM_NAME__Pref1>;

struct Foo {
  template <typename CfgElm> void get() const {
    auto it = cache_.find(CfgElm::name);
    assert(it != cache_.end());
  }
    Foo();

private:
  struct CmpCStr final {
    bool operator()(const char *a, const char *b) const {
      return std::strcmp(a, b) < 0;
    }
  };

  using PrefCacheMap = std::map<const char *, int, CmpCStr>;
  PrefCacheMap cache_;
};

and use it like this:

#include "test.hpp"

void f()
{
    Foo foo;
    foo.get<Pref1>();
}

This is reduced example, so Foo::get do nothing.

clang produces such warning for this code:

clang++ -Wall -Wextra -std=c++11 test.cpp test2.cpp
In file included from test2.cpp:1:
./test.hpp:15:35: warning: instantiation of variable 'Boo<int,
      CFG_ELM_NAME__Pref1>::name' required here, but no definition is
      available [-Wundefined-var-template]
    auto it = cache_.find(CfgElm::name);
                                  ^
test2.cpp:6:6: note: in instantiation of function template specialization
      'Foo::get<Boo<int, CFG_ELM_NAME__Pref1> >' requested here
        foo.get<Pref1>();
            ^
./test.hpp:7:21: note: forward declaration of template entity is here
  static const char name[];
                    ^
./test.hpp:15:35: note: add an explicit instantiation declaration to
      suppress this warning if 'Boo<int, CFG_ELM_NAME__Pref1>::name' is
      explicitly instantiated in another translation unit
    auto it = cache_.find(CfgElm::name);

This codes does compiles and links without problems. The only problem is warning. I have no idea how to suppress it.

I found this question explicit instantiation of static variable of a template class in different translation units , but I can not use provided solution, because of I don't know template arguments.

I can not write: template<> int Boo<Type1, Type2>::name; because of the whole idea is to use my code like this: foo.get<Pref1>(), without explicitly pointing that Pref1 is Boo<int, CFG_ELM_NAME__Pref1>.

So anybody know how to suppress warning, without turn of such warning for whole project via -Wno-undefined-var-template?

Aucun commentaire:

Enregistrer un commentaire