私が遭遇する幸運を持っていた私の最も愛された/邪悪な発明の1つは 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;
}
そして、私たちは それを使う として
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");
ちなみに、これは C++メタプログラミングでの状態の保存? に直接矛盾します。
これは CWGのアクティブな問題2118 です。
テンプレートでフレンド関数を定義し、後でその関数を参照することで、メタプログラミングの状態を取得および取得する手段が提供されます。この手法は難解であり、不正な形式にする必要があります。
2015年5月の会議のメモ:
CWGは、そのような手法を不正な形式にすべきであることに同意しましたが、それらを禁止するメカニズムはまだ不明です。
それはまだアクティブな問題であり、少なくとも今のところC++ 17では何も変更されません。ただし、そのような禁止メカニズムが決定された場合は、遡及的にDRと見なされることがあります。