Class with static member being a derived instance of the class itself : compilation issue

huangapple go评论74阅读模式
英文:

Class with static member being a derived instance of the class itself : compilation issue

问题

这不是一个非常整洁的想法,但我打算写一个类,其中一个静态成员是它自身的派生实例。 (实际上,我的类是一种抽象容器,出于性能原因,我正在共享一个简单空容器的具体实例)。

我检查了这段代码,编译正常:

class B;

class A {
public :
  static B b;
};

class B : public A
{};

int main()
{
 A a;
}

但我的类实际上是一个模板类:

template<typename T>
class B;

template<typename T>
class A {
public :
  static B<T> b;
};

template<typename T>
class B : public A<T>
{};

int main()
{
 A<int> a;
}

不幸的是,现在我遇到了编译错误:

main_ko2.cpp: In instantiation of class B<int>:
main_ko2.cpp:7:15:   required from class A<int>
main_ko2.cpp:14:9:   required from here
main_ko2.cpp:10:7: error: invalid use of incomplete type class A<int>
   10 | class B : public A<T>
      |       ^
main_ko2.cpp:5:7: note: declaration of class A<int>
    5 | class A {
      |       ^

请注意,如果我在我的 main() 函数中添加以下行

int main()
{
 B<int> b; //!< added
 A<int> a;
}

现在,代码可以编译!

由于这是一个不常见(可能有充分理由)的编程模式,也许我站在编译器行为未指定的暗区。也许其他编译器的行为会与我的不同:g++(Ubuntu 11.3.0-1ubuntu1~22.04 11.3.0)

你觉得呢?会不会有什么诀窍使编译能正常工作?

我认为创建全局变量不是一个好的解决方案,因为我希望在模板参数中有任何类型的实例。

英文:

It is not a very neat idea. but, I intend to write a class with a static member being a derived instance of itself. (actually, my class is a kind of abstract container and I am sharing a concrete instance of a simple empty container for performance reasons).

I checked this code and it compiles OK :

class B;

class A {
public :
  static B b;
};

class B : public A
{};

int main()
{
 A a;
}  

But my class is actually a template one :

template<typename T>
class B;

template<typename T>
class A {
public :
  static B<T> b;
};

template<typename T>
class B : public A<T>
{};

int main()
{
 A<int> a;
}

Unfortnuately, I now have a compiler error :

main_ko2.cpp: In instantiation of ‘class B<int>’:
main_ko2.cpp:7:15:   required from ‘class A<int>’
main_ko2.cpp:14:9:   required from here
main_ko2.cpp:10:7: error: invalid use of incomplete type ‘class A<int>’
   10 | class B : public A<T>
      |       ^
main_ko2.cpp:5:7: note: declaration of ‘class A<int>’
    5 | class A {
      |       ^

Note that if I add the following line in my main() function

int main()
{
 B<int> b; //!< added
 A<int> a;
}

Now, the code compiles OK !

As it is an uncommon (probably for good reason) programming pattern, maybe I stand in the dark areas where compiler behavior is unspecified. Maybe other compilers would behave differently than mine : g++ (Ubuntu 11.3.0-1ubuntu1~22.04 11.3.0)

What do you think ? Would there be a trick to make the compilation works ?

I don't think creating global variables would be a good solution as I want an instance for any types in my template argument.

答案1

得分: 2

你可以通过使用在第一次调用时创建实例的静态函数来避免你的错误和静态初始化顺序问题。然后,你可以在B完全定义后定义这个方法:

template<typename T>
class A {
public:
  static A& instance();
};

template<typename T>
class B : public A<T>
{};

template<typename T>
A<T>& A<T>::instance()
{
    static B<T> b;
    return b;
}
英文:

You can avoid both your error and the Static Initialization Order Fiasco by using a function static which creates your instance when it's first called. You can then define this method once B is fully defined:

template&lt;typename T&gt;
class A {
public :
  static A&amp; instance();
};

template&lt;typename T&gt;
class B : public A&lt;T&gt;
{};

template&lt;typename T&gt;
A&lt;T&gt;&amp; A&lt;T&gt;::instance()
{
    static B&lt;T&gt; b;
    return b;
}

huangapple
  • 本文由 发表于 2023年5月11日 18:52:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/76226835.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定