C++ CRTP中静态模板成员的初始化

C++ CRTP中静态模板成员的初始化,c++,static,crtp,C++,Static,Crtp,我尝试初始化CRTP基类的静态成员。基类保存派生类的静态模板成员,而派生类定义其他数据成员。我想静态初始化这个变量。在代码中,最简单的示例如下: template<typename DERIVED> class base { public: static DERIVED x; }; class derived : public base<derived> { public: int a; }; int bas

我尝试初始化CRTP基类的静态成员。基类保存派生类的静态模板成员,而派生类定义其他数据成员。我想静态初始化这个变量。在代码中,最简单的示例如下:

template<typename DERIVED>
class base {
    public:
        static DERIVED x;   
};

class derived : public base<derived>
{
    public:
        int a;   
};

int base<derived>::x {0};

int main()
{}
模板
阶级基础{
公众:
静态导出x;
};
派生类:公共基
{
公众:
INTA;
};
int base::x{0};
int main()
{}
但是,上面的代码不会编译,但会给出错误消息
error:specialized member'base::x'需要'template'语法
。 如何使静态初始化工作?

正确的语法是:

template <class T>
class base {
  public:
    static T x;   
};

template <class T>
T base<T>::x{};
编辑:要专门化
x
及其特定类型的初始化
T
,必须专门化
base
本身。即:

class A;

template <>
class base<A> {
  public:
    static int x;   
};

// Note missing "template <>" here.
int base<A>::x{ 5 };

class A : public base<A> { };
A类;
模板
阶级基础{
公众:
静态int x;
};
//注意,此处缺少“模板”。
int base::x{5};
A类:公共基{};

这似乎相当麻烦,因为在本例中,在声明专门化之前,您需要已经向前声明
A
。对我来说,你可能想重新考虑你的设计。这真的是必需的还是有一种更简单的方法来实现你想要的?

我发现了静态初始化技巧,它在上述设置中也有效。对其进行了描述和分析。在上述情况下,情况如下:

#include <iostream>

template<typename DERIVED>
class base {
    public:
        static inline DERIVED x;   
};

class derived : public base<derived>
{
    public:
        int a;
        
        struct static_initializer {
            static_initializer()
            {
                derived::x.a = 1;
            }
        };
         
        static inline static_initializer static_initializer_;        
};

int main()
{
    std::cout << derived::x.a << "\n";
}
#包括
模板
阶级基础{
公众:
静态内联派生x;
};
派生类:公共基
{
公众:
INTA;
结构静态初始化器{
静态初始化器()
{
派生::x.a=1;
}
};
静态内联静态初始化器静态初始化器;
};
int main()
{

std::cout
derived
不是一个类名,它没有在任何地方定义。谢谢你的回答。是的,我忘了指出公共继承。我知道我可以按照你的建议进行初始化。但是,当我使用上述给定的派生类时,我特别想初始化这个案例,并且只针对这个案例。来自base可以以不同的方式处理初始化。@PaulSwoboda在这种情况下,您必须专门化基类。请参阅我更新的答案。这似乎会破坏安装的目的,因为我无法为不同的派生类共享基类。@PaulSwoboda这只是使用CRTP的一种效果。您的基类是模板化的,so对于每个不同的派生类,它将始终是不同的类型。根据您的实际用例,您可以使
base
从非模板基类派生。此外,如果这回答了您的问题,请向上投票/接受。
#include <iostream>

template<typename DERIVED>
class base {
    public:
        static inline DERIVED x;   
};

class derived : public base<derived>
{
    public:
        int a;
        
        struct static_initializer {
            static_initializer()
            {
                derived::x.a = 1;
            }
        };
         
        static inline static_initializer static_initializer_;        
};

int main()
{
    std::cout << derived::x.a << "\n";
}