有状态的元编程是否形成不良(尚)?

Pas*_* By 40 c++ metaprogramming language-lawyer c++17

我有幸遇到的最让我最喜爱/最邪恶的发明之一是constexpr计数器,也就是有状态的元编程.正如帖子中所提到的,它似乎在C++ 14下是合法的,我想知道C++ 17有什么变化吗?

以下是主要基于帖子的实现

template <int N>
struct flag
{
    friend constexpr int adl_flag(flag<N>);
    constexpr operator int() { return N; }
};

template <int N>
struct write
{
    friend constexpr int adl_flag(flag<N>) { return N; }
    static constexpr int value = N;
};

template <int N, int = adl_flag(flag<N>{})>
constexpr int read(int, flag<N>, int R = read(0, flag<N + 1>{}))
{
    return R;
}

template <int N>
constexpr int read(float, flag<N>)
{
    return N;
}

template <int N = 0>
constexpr int counter(int R = write<read(0, flag<0>{}) + N>::value)
{
    return R;
}
Run Code Online (Sandbox Code Playgroud)

我们用它作为

static_assert(counter() != counter(), "Your compiler is mad at you"); 

template<int = counter()>
struct S {};

static_assert(!std::is_same_v<S<>, S<>>, "This is ridiculous");
Run Code Online (Sandbox Code Playgroud)

顺便说一下,这与C++ Metaprogramming中的存储状态直接矛盾吗?

Bar*_*rry 37

这是CWG活动问题2118:

在模板中定义友元函数,然后引用该函数提供了捕获和检索元编程状态的方法.这种技术是神秘的,应该是不正确的.

2015年5月会议记录:

CWG同意这些技术应该是不正确的,尽管禁止它们的机制尚未确定.

它仍然是一个活跃的问题,至少目前在C++ 17中没有任何改变.虽然确定了这种禁止机制,但这可能会被追溯性地裁定为DR.

  • “这种技术是神秘的(_i.e. 被少数人理解,神秘,秘密_)”真的意味着它“应该变得不正确”?我们今天使用的许多 _standard_ c++ 习语基本上都是从这种方式开始的(TMP、CRTP、ADL 仅举几例)。 (6认同)
  • @DavisHerring:但是,我很想知道他们将如何使这种格式不正确。与原始问题中使用的机制(利用 C++20 功能的机制)相比,有更好且更多“受支持”的机制来执行有状态元编程。编译器实际上必须检测不良用法并专门阻止该用法,同时让该用法被认为是可接受的。我不确定这是否可能!更好的是,有人创建了一个使用这些有状态元编程功能的 boost 库,那么它将成为该语言的一流功能! (2认同)