具有'using'的模板模板成员继承

template template member inheritance with 'using'

本文关键字:继承 成员 using 具有      更新时间:2023-10-16

以下类实现 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;
    }
};

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

避免

注入类名的更简单的解决方法是使用全名::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;
    }
};

演示

代码使用 gcc/clang 演示正确编译。

这是一个 msvc 错误,因为

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

  • 其次是<</li>
  • 它用作与模板模板参数对应的模板参数
  • 它是友元类模板声明的详细类说明符中的最终标识符。