可以创建任意类型的constexpr链接列表吗?

时间:2019-07-31 15:54:02

标签: c++ c++11 traits constexpr

我正在尝试实现基于特征的策略子系统,但是我有一个我真的不知道该如何解决的问题(如果可能的话)。我有一个看起来像这样的特征:

template <typename ValueT, typename TagT = void, typename EnableT = void>
struct TPolicyTraits
{
    static void Apply(ValueT& value) { }
};

这个特征可以这样具体化:

struct MyPolicy {};

template <typename ValueT>
struct TPolicyTraits<ValueT, MyPolicy>
{
    static void Apply(ValueT& value) { /* Implementation */ }
};

我想在编译时以某种链表的形式注册策略。政策系统将像这样使用:

namespace PolicyTraits
{
    template <typename ValueT, typename TagT>
    using TPolicyTraitsOf = TPolicyTraits<std::decay_t<ValueT>, TagT>;

    template <typename ValueT>
    void Apply(ValueT&& value) 
    {
        // todo iterate through constexpr tag list and apply policies
    }

    template <typename TagT>
    constexpr void Enable()
    {
        // todo add tag to constexpr list
    }
}

int main()
{
    PolicyTraits::Enable<MyPolicy>();
    PolicyTraits::Apply(std::string());
}

有什么办法可以做到这一点?

2 个答案:

答案 0 :(得分:5)

大多数情况下,编译时元编程是纯程序。这意味着每个表达式的结果取决于其参数。

坦白地说,通过使用依赖于参数的查找和友元函数以及SFINAE可以解决此问题。

不要那样做。

从其策略中构建策略特征类,不要四处寻找全局状态。

TL; DR从技术上来说是可行的,但是这是一个可怕的想法。不要这样做。

与您描述的问题相邻的问题可能是干净而优雅的解决方案。

答案 1 :(得分:1)

否。

constexpr可能无法使用new分配内存。该限制可能最终会被消除。但是目前,就是这样。

这排除了使用任何动态大小的数据类型。

OTOH,constexpr使您可以相对轻松地创建具有计算大小的静态大小的数据类型(前提是可以在编译时完成计算)。可以利用它来做您想要的事情。

除了在多个不同的编译单元之间构建这样的类型之外,再也无法做到。而且该限制是C ++编译/链接链的固有功能,如果不进行重大更改就无法删除。

所以,不。