Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 有状态元编程的格式是否不正确?_C++_Language Lawyer_Metaprogramming_C++17 - Fatal编程技术网

C++ 有状态元编程的格式是否不正确?

C++ 有状态元编程的格式是否不正确?,c++,language-lawyer,metaprogramming,c++17,C++,Language Lawyer,Metaprogramming,C++17,我有幸遇到的最受我喜爱/最邪恶的发明之一就是有状态元编程(statefulmetaprogramming)。正如在文章中提到的,它在C++14下似乎是合法的,我想知道C++17有什么变化吗 下面是一个主要基于post的实现 template <int N> struct flag { friend constexpr int adl_flag(flag<N>); constexpr operator int() { return N; } }; temp

我有幸遇到的最受我喜爱/最邪恶的发明之一就是有状态元编程(statefulmetaprogramming)。正如在文章中提到的,它在C++14下似乎是合法的,我想知道C++17有什么变化吗

下面是一个主要基于post的实现

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;
}
模板
结构标志
{
friend constexpr int adl_标志(标志);
constexpr运算符int(){return N;}
};
模板
结构写入
{
friend constexpr int adl_标志(标志){return N;}
静态constexpr int value=N;
};
模板
constexpr int read(int,flag,int R=read(0,flag{}))
{
返回R;
}
模板
constexpr int read(浮点,标志)
{
返回N;
}
模板
constexpr int计数器(int R=write::value)
{
返回R;
}
我们作为

static_断言(counter()!=counter(),“你的编译器生你的气了”);
模板
结构S{};
静态断言(!std::is_same_v,“这太荒谬了”);
顺便说一句,这与以下内容直接矛盾:

在模板中定义友元函数,然后稍后引用该函数提供了一种捕获和检索元编程状态的方法。这是一种神秘的技术,应该使其变形

2015年5月会议记录:

CWG同意,这种技术应该是格式错误的,尽管禁止它们的机制尚未确定


这仍然是一个活跃的问题,至少目前在C++17中不会有任何改变。虽然当确定了这样一种禁止机制时,这可以追溯到DR。

如何
read(0,flag{})
不导致无限循环?文本0导致它调用第一个重载(
int
优先于
float
),后者自然会一次又一次地调用它。终止条件是什么?@NicolBolas By SFINAE,对于足够大的
N
,不能调用
int
读取(0,标志{})的
重载,因为我们还没有定义
adl_标志(标志)
,因此将调用
float
重载。对于完整的解释,链接的帖子写得很好。还要注意大卫·克劳斯在相应的帖子中指出的缺陷,菲利普承诺在第四篇帖子中解决,但从未解决过。这太糟糕了,我喜欢它!编译器是否真的需要在每次使用模板时重新计算默认模板参数(不指定该参数)?“这种技术是神秘的(即少数人理解的、神秘的、秘密的)”是否真的意味着“应该使其格式错误”?我们今天的许多C++习语基本上都是这样开始的(TMP,CRTP,ADL)。
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");