避免模板类中的重定义错误

Avoid redefinition error in template class

本文关键字:定义 错误      更新时间:2023-10-16

出于IO目的,我需要与各种类型的字符串相关联。为此,我创建了一个模板类names,它专门用于我需要命名的每个类型。这是头文件:

template<typename T>
class names {};
template<>
class names<Index> {
public:
static const std::string name;
};
template<>
class names<Integer> {
public:
static const std::string name;
};

以及相应的源文件:

const std::string names<Index>::name = "Index";
const std::string names<Integer>::name = "Integer";

IndexInteger通过typedef定义:

typedef std::ptrdiff_t Index;
typedef int Integer;

该代码在我使用的macOS和Ubuntu机器上编译并运行良好。但是,在 Windows 计算机上,std::ptrdiff_t定义为int。然后我收到以下错误:

In file included from lib/mixt_MixtComp.h:22:0,
from dummy.cpp:5:
lib/LinAlg/names.h:28:7: error: redefinition of 'class mixt::names<int>'
class names<Integer> {
^
lib/LinAlg/names.h:22:7: error: previous definition of 'class mixt::names<int>'
class names<Index> {
^

有没有办法避免此错误?我可以使用C++11。

您有两个选择:

  1. 在 Windows 上,只选择一个专业,不要定义另一个。(哎呀(
  2. 这里真正需要的是一个强大的 typedef,而不仅仅是一个瘦类型别名。您需要IndexInteger实际上是不同的类型,而不仅仅是在两种情况下可能相同的其他名称。

    如果你不介意在使用这些类型进行算术时有点麻烦,那么作用域枚举可能是合适的:

    enum class Index   : std::ptrdiff_t {};
    enum class Integer : int {};
    

    现在这两种类型是不同的,但"继承"了你想要的,它们不会相互冲突,甚至不会隐式地相互转换。它可以在你的UNIXy平台和Windows盒子上运行。

    事实上,如果这些类型不应该在算术中使用,那么作用域枚举的属性实际上是正确的。

一般来说,我倾向于避免typedef.它有其用于缩短长名称的用途(尽管为了清楚起见,现在更喜欢using X = Y(,但对于几乎所有其他事情,您都在乞求您在这里发现的那种麻烦。