模板类中的静态常量类型

发布于 2024-12-26 03:30:12 字数 344 浏览 1 评论 0原文

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

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

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

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

I've been doing some research into this problem but haven't yet been able to come up with a solution. Basically I need to initialize a static const type variable inside a template class.

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

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

Initializing Type inside the cpp will produce a linker error. Initializing Type inside the header will cause it to be initialized multiple times. Initializing Type inside the class cannot be done due it being a non-integral type. How can I solve this problem without limiting class specialization. Any help is appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情场扛把子 2025-01-02 03:30:12

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

我的猜测是,您尝试在某个 cpp 文件中定义类似这样的对象:

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

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

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

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

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

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

I'm not sure what you mean by "initializing Type inside the cpp will produce a linker error." but assuming you actually mean defining then you must have done something wrong because defining the static member for every type in an appropriate location certainly works! What you have in you class template is a declaration of an object and this needs to be defined somewhere if it ever referenced. Only if MyType happens to be an integral type, you initialize it in your class [template], and you never need its address (e.g. bind it to a constant reference or take its address) you get away with not defining it. This is because it is always treated as a constant expression in this case.

My guess is that you tried to define your object something like this in some cpp file:

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

This won't work unless you also instantiate this definition either explicitly or implicitly in the same translation unit. You can define the member for a specific type something like this:

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

Unless you actually need the type to be a constant expression in which case you can typically side-step the problem, if necessary by making it an enum (this is what I tend to do because this guy can be bound to const reference without requiring a definition), you can use a static member function which can be defined in the header instead:

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

BTW, I'm pretty sure this question was answered before, definitely in comp.lang.c++.moderated.

看透却不说透 2025-01-02 03:30:12

初始化标头内的 Type 将导致其被初始化多次。

嗯,当然。对于实例化 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 所示。这些函数局部静态优于任何其他类型的静态对象,因为使用它们时不会遇到静态初始化顺序惨败。

Initializing Type inside the header will cause it to be initialized multiple times.

Well, of course. One time for every different type that MyClass is instantiated with. It's also a different object for every type, that's inherent to how templates work. If you only want it defined and initialized once, put it in a non-template base:

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
};

Now you can just put

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

in a .cpp and be done with it.


Note that it would generally be better to encapsulate the static object inside a function, as @Dietmar shows. Those function-local statics are superior to any other kind of static object, because you won't run into the static initialization order fiasco when using them.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文