模板 class 字段的显式实例化声明

explicit instantiation declaration of template class field

我有这样的 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_;
};

并像这样使用它 (test2.cpp):

#include "test.hpp"

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

并像这样初始化它 (test.cpp):

#include "test.hpp"

template <> const char Pref1::name[] = "Pref1";

Foo::Foo()
{
    cache_.insert(std::make_pair(Pref1::name, 17));
}

这是简化的例子,所以Foo::get什么都不做。

clang 对此代码产生这样的警告:

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

这段代码编译和链接没有问题。 唯一的问题是警告。 我不知道如何抑制它。

我发现了这个问题 explicit instantiation of static variable of a template class in different translation units ,但我无法使用提供的解决方案,因为我不知道模板参数。

我不会写:template<> int Boo<Type1, Type2>::name; 因为整个想法是像这样使用我的代码:foo.get<Pref1>(),没有明确指出 Pref1Boo<int, CFG_ELM_NAME__Pref1>.

所以有人知道如何抑制警告,而不通过 -Wno-undefined-var-template 对整个项目发出此类警告吗?

您应该在同一头文件中添加 Boo::name 模板定义:

   static const char * name;
}; // End Boo 

template<typename T, typename Tag> 
const char * Boo<T, Tag>::name{};

更新:现在已明确您正在尝试在某个翻译单元中为 name 编写专业化 之后在头文件中对其进行实例化。这将需要一些技巧。您需要在 实例化它之前在头文件 中声明专业化,并且可能使用外部模板并在与 name:

相同的翻译单元中显式实例化它
// header

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

struct CFG_ELM_NAME__Pref1 {};

// indicate that name for this specialization exists elsewhere
template<> const char * Boo<int, CFG_ELM_NAME__Pref1>::name;

// indicate that template is defined somewhere
extern template struct Boo<int, CFG_ELM_NAME__Pref1>;

using Pref1 = Boo<int, CFG_ELM_NAME__Pref1>;

// test.cpp

// definition will be present only in this translation unit
template<> const char * Boo<int, CFG_ELM_NAME__Pref1>::name{"Pref1"};

// explicit instantiation
template struct Boo<int, CFG_ELM_NAME__Pref1>;

online compiler