【问题标题】:c++ static polymorphism (CRTP) Resulting in incomplete type when evaluating a `static constexpr`c ++静态多态性(CRTP)在评估`static constexpr`时导致类型不完整
【发布时间】:2019-03-19 13:27:34
【问题描述】:

我需要访问static constexpr,而我整合的一个解决方案适用于 gcc (live example),但不适用于 vc++ (live example)。

代码如下:

template<class Drvd>
class Base
{
public:
    static constexpr bool val = Drvd::val;
};

class Derived : public Base<Derived>
{
    friend class Base;
private:
    static constexpr bool val = true;
};

int main()
{
    std::cout << Derived::Base::val << std::endl;
}

所以这是 vc++ 的一个错误,但任何人都知道如何以 vc++ 不会抱怨的不同方式实现 Base 中定义的 val 作为 Drvd 中 val 的值?

编辑: 请注意,结果与变体相同:friend class Base&lt;Derived&gt;; 而不是 friend class Base;

【问题讨论】:

标签: c++ visual-c++ metaprogramming crtp static-polymorphism


【解决方案1】:

你可以使用一个方法:

#include <iostream>

template<class Drvd>
class Base
{
public:
    static constexpr bool val() { return Drvd::val;  }
};

class Derived : public Base<Derived>
{
    friend class Base<Derived>;
private:
    static constexpr bool val = true;
};

int main()
{
    std::cout << Derived::Base::val() << std::endl;
}

实时示例:https://rextester.com/IHR24393

【讨论】:

  • 不错的变体,但我不得不求助于添加()。如果不出意外,我想这将不得不这样做。谢谢。
  • 另一条评论,使用constexpr 函数,虽然适用于这种特殊情况,但也限制了将val() 用作模板参数。
【解决方案2】:

您的问题不在于私有/朋友声明(即使 “val”是公开的),你的问题是在

的实例化期间
static constexpr bool val = Drvd::val

Drvd 仍然是不完整的类型。 请参阅下面有关如何使用特征类解决此问题的问题/答案。

C++ static polymorphism (CRTP) and using typedefs from derived classes

附:事实上,我只是将您的问题标记为重复

【讨论】:

  • 谢谢,这似乎是正确的方向。虽然我不确定是不是直接重复,但我会尝试在其他页面上玩一下,看看有什么结果。
【解决方案3】:

根据@David,问题与Face 不完整有关,因为它在完成Face 的定义之前进入Base。

但是,@David 链接的解决方案有点陈旧,并且遗漏了一些我们可以利用的技巧。即,@m.s.向我们展示了 static constexpr 函数很好 - 也是基于我自己的实验 - 我们真的只需要处理 static constexpr 变量的这种特殊情况,也许是从 Derived 访问的类型。

以下 (live example) 展示了如何解决此问题,同时将每个类封装到自己的 h 文件中,使其更加简洁:

#include <iostream>

// Begin: h-file of Base
template<class Drvd>
class ConstValue;

template<class Drvd>
class Base
{
public:
    static constexpr bool val = ConstValue<Drvd>::val;
};
// End: h-file of Base

// Begin: h-file of Derived
class Derived;

template<>
class ConstValue<Derived>
{
public:
    static constexpr bool val = true;
};

class Derived : public Base<Derived>
{
    friend class Base<Derived>;
private:
    static constexpr bool val = true; // optional
};
// End: h-file of Derived

// Main
int main()
{
    std::cout << Derived::Base::val << std::endl;
}

一般的想法是,对于Base需要从Derived访问的每个constexpr,我们可以创建一个封装变量的单个类,然后为每个使用@987654333的Derived重载该类@。

【讨论】:

    猜你喜欢
    • 2015-02-25
    • 1970-01-01
    • 1970-01-01
    • 2011-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多