【问题标题】:static const types in template classes模板类中的静态 const 类型
【发布时间】:2012-01-08 19:58:17
【问题描述】:

我一直在对这个问题进行一些研究,但还没有提出解决方案。基本上我需要在模板类中初始化一个静态 const 类型变量。

class MyType
{
public:
    MyType (int a, int b) { }
};

template <class T>
class MyClass
{
public:
    static const MyType Type;
};

在 cpp 中初始化类型会产生链接器错误。在标头中初始化类型将导致它被多次初始化。由于它是非整数类型,因此无法在类中初始化类型。如何在不限制类专业化的情况下解决这个问题。任何帮助表示赞赏。

【问题讨论】:

  • "在头部初始化类型会导致它被多次初始化。"你能举个例子说明你是怎么做的吗?如果您只是检查构造函数是否被多次调用,则应该多次调用它,因为每个模板类实例化都有一个成员。

标签: c++ templates static-variables


【解决方案1】:

我不确定您所说的“在 cpp 中初始化 Type 会产生链接器错误”是什么意思。但是假设您实际上是指定义,那么您一定做错了什么,因为在适当的位置为每种类型定义静态成员肯定有效!您在类模板中拥有的是一个对象的声明,如果它曾经被引用,则需要在某个地方定义它。只有当MyType 恰好是一个整数类型时,你才在你的类 [模板] 中初始化它,并且你永远不需要它的地址(例如,将它绑定到一个常量引用或获取它的地址)你不定义它就可以逃脱。这是因为在这种情况下它总是被视为常量表达式。

我的猜测是你试图在一些 cpp 文件中定义你的对象:

template <typename T> MyType const MyClass<T>::Type = some-initialization-here;

除非您还在同一翻译单元中显式或隐式实例化此定义,否则这将不起作用。您可以为特定类型定义成员,如下所示:

template <> MyType const MyClass<T>::Type = some-initialization-here;

除非您实际上需要将类型设为常量表达式,在这种情况下,您通常可以回避问题,如有必要,将其设为 enum(这是我倾向于做的事情,因为这家伙可以绑定到const 引用而不需要定义),您可以使用可以在标题中定义的静态成员函数:

template <typename T>
MyType const& MyClass<T>::Type() {
    static MyType rc = some-initialization-here;
    return rc;
}

顺便说一句,我很确定这个问题之前已经回答过了,肯定是在comp.lang.c++.moderated

【讨论】:

  • 请注意,该函数仍会导致MyClass 包含多个MyType 对象。除此之外,+1。函数局部静态优于类局部或全局静态,仅仅是因为它们没有静态初始化顺序失败。
  • @Xeo:好吧,当然:每次实例化都有一个对象。如果您不希望这样,则需要将静态成员分解为通用的 [非模板化] 基类。
【解决方案2】:

在头部初始化类型会导致它被多次初始化。

嗯,当然。对MyClass 实例化的每种不同类型都有一次。对于每种类型,它也是一个不同的对象,这是模板工作方式所固有的。如果您只想定义和初始化一次,请将其放在非模板库中:

namespace detail{
class MyClassBase{
protected:
  ~MyClassBase(){} // only usable as a base class, non-polymorphic
  static const MyType Type; // only available to derived types
};
} // detail::

template<class T>
class MyClass
  : private detail::MyClassBase // private, non-polymorphic
{
public:
  using MyClassBase::Type; // if you want to expose 'Type' to the public audience
};

现在你可以放

const MyType detail::MyClassBase::Type = /*initialize here*/;

在 .cpp 中并完成它。


请注意,正如@Dietmar 所示,将static 对象封装在函数中通常会更好。这些函数局部的静态变量优于任何其他类型的静态对象,因为在使用它们时您不会遇到静态初始化顺序惨败。

【讨论】:

    猜你喜欢
    • 2012-12-13
    • 1970-01-01
    • 1970-01-01
    • 2011-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多