C++ 模板类字段的显式实例化声明

C++ 模板类字段的显式实例化声明,c++,c++11,templates,clang++,C++,C++11,Templates,Clang++,我有这样的测试.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<i

我有这样的
测试.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_;
};
#include "test.hpp"

void f()
{
    Foo foo;
    foo.get<Pref1>();
}
#include "test.hpp"

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

Foo::Foo()
{
    cache_.insert(std::make_pair(Pref1::name, 17));
}
然后像这样初始化它(
test.cpp
):

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

我发现了这个问题,但我不能使用提供的解决方案,因为我不知道模板参数

我不会写:
template int Boo::name
因为整个想法是这样使用我的代码:
foo.get()
,而不明确指出
Pref1
Boo


因此,任何人都知道如何通过
-Wno undefined var template

抑制警告,而不必通过
-Wno undefined var template对整个项目发出警告,您应该在同一头文件中添加
Boo::name
模板定义:

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

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

它可以工作,但我必须删除
*
并添加
[]{}
,使其编译时不会出错。但在最后,初始化意味着什么呢?但是我在other
.cpp
中的init
name
没有显示在我的问题中。@user1244932
{}
末尾是一个。在
.cpp
中初始化
name
不是一个好主意,请参阅。我不会在cpp中初始化整个模板,而是初始化具体类型,如下所示
template const char Pref1::name[]=“Pref1”我已经更新了我的问题,以显示我如何初始化
name
。我尝试了您的解决方案,它可以在链接时间内使用
clang++
,但是
g++-Wall-Wextra-std=c++11 test.cpp test2.cpp
返回
名称的多个定义
,但是在没有
模板const char*Boo::name{}的情况下编译得很好我使用了clang 5.0.1和gcc 7.2.1。
   static const char * name;
}; // End Boo 

template<typename T, typename Tag> 
const char * Boo<T, Tag>::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>;