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

时间:2018-10-18 09:51:22

标签: c++ c++11

出于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 个答案:

答案 0 :(得分:3)

您有两个选择:

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

    如果在使用这些类型进行算术时不介意一点麻烦,则可以使用范围限定的枚举:

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

    现在,这两种类型是与您想要的类型截然不同但“继承”的,并且它们不会发生冲突,甚至不会相互隐式转换。 on your UNIXy platformson your Windows box都可以使用。

    实际上,如果不是假定来使用这些类型,则实际上会发现作用域枚举的属性。

通常,我倾向于避免使用typedef。它具有缩短长名的作用(尽管今天为了清楚起见,更喜欢使用using X = Y),但是对于几乎其他所有情况,您都只是乞求在这里发现的麻烦。