【问题标题】:template template member inheritance with 'using'使用“使用”的模板模板成员继承
【发布时间】:2019-05-31 16:10:10
【问题描述】:

以下类实现 CRTP。我想让Derived类使用Base提供的构造函数,所以我写using。但是,我收到错误消息“只能从直接基类继承构造函数”。等效于成员变量x


template<template<typename, size_t> typename G, typename F, size_t U>
struct Base
{
    double x;
    Base(double x) : x{ x } {}
    double gimme_x()
    {
        return (*static_cast<G<F, U>*>(this)).gimme_x();
    }
};

template<typename F, size_t U>
struct Derived : Base<Derived, double, U>
{
    using Base<Derived, double, U>::Base;
    using Base<Derived, double, U>::x;

    double gimme_x()
    {
        return x + 1.8;
    }
};

可以通过将 Base 的模板模板实现更改为仅使用常规模板来缓解此问题。


template<typename G, typename F, size_t U>
struct Base
{
    double x;
    Base(double x) : x{ x } {}
    double gimme_x()
    {
        return (*static_cast<G*>(this)).gimme_x();
    }
};

template<typename F, size_t U>
struct Derived : Base<Derived<F, U>, double, U>
{
    using Base<Derived<F, U>, double, U>::Base;
    using Base<Derived<F, U>, double, U>::x;

    double gimme_x()
    {
        return x + 1.8;
    }
};

虽然第二个看起来有点冗长,但在这种情况下,它似乎应该等同于第一个。有什么区别,为什么第一个的实现会失败?

【问题讨论】:

    标签: c++ templates inheritance visual-c++


    【解决方案1】:

    避免injected-class-name 的更简单的解决方法是使用全名::Derived

    template<typename F, size_t U>
    struct Derived : Base<Derived, double, U>
    {
        using Base<::Derived, double, U>::Base;
        using Base<::Derived, double, U>::x;
    
        double gimme_x()
        {
            return x + 1.8;
        }
    };
    

    Demo

    使用 gcc/clang Demo 都可以正确编译代码。

    这是一个 msvc 错误,因为

    在以下情况下,注入的类名被视为类模板本身的模板名:

    • 后面是
    • 用作模板参数,对应一个模板模板参数
    • 它是友元类模板声明的详细类说明符中的最终标识符。

    【讨论】:

    • 原始代码无法在 Visual c++ 中编译,但解决方法解决了它。
    猜你喜欢
    • 2018-12-03
    • 1970-01-01
    • 2015-04-18
    • 1970-01-01
    • 2012-10-26
    • 2015-01-30
    • 2012-03-13
    • 2016-12-03
    • 2016-02-21
    相关资源
    最近更新 更多