使用is作为模板类型参数时,我可以访问类字段吗?

jay*_*ubi 1 c++ templates

我知道这段代码看起来很奇怪,但我想知道是否有任何方法可以使它编译.

template<typename T>
class A
{
public:
    enum
    {
        template_class_id = T::class_id
    };
};

class B : public A<B>
{
public:
    enum
    {
        class_id = 0x1234
    };
};
Run Code Online (Sandbox Code Playgroud)

我得到这样的错误:

clang++ test.cpp                                            
test.cpp:7:32: error: no member named 'class_id' in 'B'
        template_class_id = T::class_id
                            ~~~^
test.cpp:11:18: note: in instantiation of template class 'A<B>' requested here
class B : public A<B>
                 ^
1 error generated.
Run Code Online (Sandbox Code Playgroud)

Tar*_*ama 5

BA<B>实例化基类时,它是一个不完整的类型,因此B::class_id在该点不存在.

为了得到你需要的东西,你需要延迟template_class_id成员的实例化.


一种可能性是制作template_class_idC++ 14成员变量模板:

template<typename T>
class A
{
public:
    template <typename U=T>
    static constexpr int template_class_id = U::class_id;
};

class B : public A<B>
{
public:
    static constexpr int class_id = 0x1234;
};
Run Code Online (Sandbox Code Playgroud)

Live Demo

不幸的是,这意味着你需要引用template_class_idas template_class_id<>,但它不需要任何额外的类型.


另一种选择是依靠特质类:

template <typename T> struct ClassId;

template<typename T>
class A {
public:
    static constexpr int template_class_id = ClassId<T>::value;
};

class B;
template <> struct ClassId<B> {
    static constexpr int value = 0x1234;   
};

class B : public A<B> {
};
Run Code Online (Sandbox Code Playgroud)

Live Demo

我认为这非常灵活,不需要你切换到功能.它确实意味着id在词法上超出了你的类定义,但我认为这不是一个大问题.