在派生类中缺少静态成员变量时强制编译错误

时间:2015-02-26 08:49:14

标签: c++ templates static-members typetraits

假设以下类层次结构:

//file base.h
class IBase
{
public:
    virtual ~IBase() = default;

    //a static member identifying IBase (e.g. "iid.base")
    static const char* const IID;  //initialize in implementation file
//[...]
};//class IBase

class IDerived : public IBase
{
public:
    virtual ~IDerived() = default;

    //a static member identifying IDerived (e.g. "iid.derived")
    static const char* const IID;  //initialize in implementation file
//[...]
};//class IDerived

class IEvenMoreDerived : public IDerived
{
public:
    virtual ~IEvenMoreDerived() = default;

    //missing static const member IID!
//[...]
};//class IEvenMoreDerived

此层次结构中的每个类都必须具有自己的static const tChar* const iid,可用于标识对象而不实例化它。在IEvenMoreDerived中,此信息丢失。

现在,在代码的某处,我有一个访问IID的函数模板:

//file main.cpp
#include "base.h"

template<typename T>
void queryIID()
{
    std::cout << T::IID << std::endl;
}

int main(int argc, char* argv[])
{
    queryIID<IBase>();             //prints "iid.base"
    queryIID<IDerived>();          //prints "iid.derived"
    queryIID<IEvenMoreDerived>();  //probably prints "iid.derived"
    return 0;
}

我的目的是在使用queryIID<IEvenMoreDerived>();时遇到编译时错误,因为IEvenMoreDerived没有静态成员iid。我假设可能在函数模板queryIID()中使用一些模板魔术,但我尝试的一切都没有解决问题。

其他一些要点:

  • 遗憾的是,使用constexpr char*代替static const char* const似乎无法实现The MS VS2015 Feature Preview,即使在VS2015中也不支持。
  • 经过一番挖掘,我遇到了C++ Templates FAQ。据此,成员隐藏是类模板的“特征”。我无法弄清楚如何使用它来解决我的问题。此外,我不希望将上面提到的类层次结构更改为类。
  • 在其他问题中,我发现this somewhat similar question on SO,但它并不完全符合我的问题。

1 个答案:

答案 0 :(得分:1)

作为一种变通方法,您可以将Id委托给外部结构,例如:

template <typename T>
struct IdName
{
    static const char* const IID;
};

// instead of `const char* const IBase::IID = "IBase";`
// you have to use the following
template <> const char* const IdName<IBase>::IID = "IBase";
// Same for IDerived
template <> const char* const IdName<IDerived>::IID = "IDerived";

尝试使用IdName<IEvenMoreDerived>::IID时出现链接错误。

Live example