代码保护失败,字符串文字模板

时间:2011-07-23 23:47:01

标签: c++ compiler-errors include-guards multiple-definition-error

我知道将字符串文字作为模板参数传递的唯一方法是在之前声明它:

档案a.h

#ifndef A_H
#define A_H

#include <string>

char EL[] = "el";


template<char* name>
struct myclass
{
  std::string get_name() { return name; }
};

typedef myclass<EL> myclass_el;

#endif

档案a.cpp

#include "a.cpp"

的main.cpp

#include "a.h"
...

g++ -c a.cpp
g++ -c main.cpp
g++ -o main main.o a.o

我得到了:

a.o:(.data+0x0): multiple definition of `EL'
main.o:(.data+0x0): first defined here
collect2: ld returned 1 exit status

我无法将EL声明为外部,我希望保留a.cpp。溶液

2 个答案:

答案 0 :(得分:3)

让我们从标准中为所有人的利益开始,从14.3.2模板非类型参数[temp.arg.nontype](C ++ 03标准):

  

1非类型非模板模板参数的模板参数   应该是以下之一:

     

- 积分或积分的整数常量表达式   枚举类型;或

     

- 非类型模板参数的名称;或

     

- 具有外部链接的对象或函数的地址,包括   函数模板和函数template-id但不包括非静态   班级成员,表达为&amp; id-expression 其中&amp;如果是可选的   名称是指函数或数组,或者是相应的   template-parameter是一个引用;或

     

- 指向成员的指针   如5.3.1中所述。

强调我的相关部分。

此外,第5段列出了允许的转换,其中一个是指针衰减的数组。第2段甚至是一个说明,表明char*与OP的使用类似。

剩下的就是如何在具有外部链接且没有错误的标题中创建对象。通常的方法是在标题中声明,在一个TU中只有一个定义。

// In header
extern char EL[]; // array of unspecified size, an incomplete type
                  // extern char EL[3] is acceptable, too.

// In source
char EL[] = "el";

请注意,static是不可能的,因为要求对象具有外部链接。如果意图是每个TU具有单独的对象,则首选未命名的命名空间。

// In header
// NOT RECOMMENDED! Be wary of ODR-violations with such constructs
// or simply only use these in source files
namespace {

// Recommend using const here, which in turn means using extern
// change non-type template parameter accordingly
extern const char EL[] = "el";

} // namespace

对于好奇,C ++ 0x放宽了对象具有外部链接作为有效参数的要求。 (我的GCC副本还不支持。)字符串文字莫名其妙地禁止显示为模板参数。

答案 1 :(得分:2)

修改后的答案(之前的回答是胡说八道。很抱歉!此外,您之前的问题应该已经完全解决了这个问题。)

部首:

#ifndef H_ABC
#define H_ABC

extern char EL[];

template <const char * S>
struct Foo
{
  static inline const char * get_name() { return S; }
  static const char * name;
};
template <const char * S> const char * Foo<S>::name(S);

typedef Foo<EL> MyElClass;

#endif

您需要一个TU来定义EL

#include "header.h"
char EL[] = "EL";

您可以在任何地方使用该模板:

#include "header.h"

char A[] = "abc";
extern const char B[] = "xyz";  // must have extern linkage!

void f() {
  std::cout << MyElClass::name << std::endl;
  std::cout << MyElClass::get_name() << std::endl;
  std::cout << Foo<A>::name << std::endl;
  std::cout << Foo<B>::name << std::endl;
}