首页 > 解决方案 > 如何在编译时从范围运算符中提取类型?

问题描述

是否有可能(不使用宏)在不带参数的静态函数中由编译器推导出模板参数?

struct Widget
{
    template<typename T = ?>
    static void foo()
    {
    }
 };

 struct Base : Widget {};
 struct Derived : Base {};

 Base::foo(); // T should be deduced as Base
 Derived::foo(); // T should be deduced as Derived

在我的用例中,编写Base::foo<Base>();不仅是多余的(编译器已经拥有该信息,正如我已经说过的那样Base::),而且还会引入出错的可能性——Base::foo<SomeOtherType>();应该禁止调用。

有没有办法在编译时区分 foo 被称为 asBase::foo()还是 as Derived::foo()

标签: c++templates

解决方案


此问题的答案中概述了像这样的多级 CRTP 层次结构的一种方法。

另一种方法是每隔一层注入基类。

#include <iostream>
#include <typeinfo>

class WidgetBase
{
};

template <class D, class B = WidgetBase>
class Widget : public B
{
  public:
    static void foo()
    {
        std::cout << typeid(D).name() << " is " << sizeof(D) << " bytes large\n";
    }
};

class Base : public Widget<Base> { int a; };

class Derived : public Widget<Derived, Base> { int b; };

class MoreDerived : public Widget<MoreDerived, Derived> { };

int main()
{
    Base::foo();
    Derived::foo();
    MoreDerived::foo();
}

推荐阅读