Tus*_*121 0 c++ c++-concepts c++20
这个相当简单:根据cppreference 文章,概念可以毫无问题地重新声明:
所以我想好吧,很酷,我不必担心重新声明我创建“可打印枚举”的概念;我可以在日志记录标头和常见类型标头中声明该概念,因此我只需包含所需的内容:
// common types header
#include <enum_traits.hpp>
template<typename E>
concept PrintableEnum = requires(E& e) { {enum_traits<E>::toString(e)} -> std::same_as<const char*>; };
template<PrintableEnum T>
std::ostream& operator<<(std::ostream& os, const T& o)
{
os << enum_traits<T>::toString(o);
return os;
}
// logging header
template<typename T>
concept PrintableEnum = requires(T& e) { {enum_traits<T>::toString(e)} -> std::same_as<const char*>; };
template<PrintableEnum T>
plog::Record& operator<<(plog::Record& rec, const T& o)
{
rec << enum_traits<T>::toString(o);
return rec;
}
Run Code Online (Sandbox Code Playgroud)
(忽略 ostream 过载可能暂时覆盖 plog 记录过载;这可能是我解决该问题的方法,但我首先对此感到好奇。)
因此,当我尝试编译此文件时,MSVC 会为包含两个标头的每个文件抛出一个合适的情况(它指向哪一个,因为错误根据包含顺序而变化):
[build] commontypes.hpp(25): error C7571: 'PrintableEnum': variable template has already been initialized
[build] logging.hpp(162): note: see declaration of 'PrintableEnum'
Run Code Online (Sandbox Code Playgroud)
另请注意,执行 cppreference 在该屏幕截图中所做的操作并在其中一个文件中的第一个声明下方复制 PrintableEnum 声明是相同的问题。
那么,这里的 cppreference 是错误的吗?该标准实际上没有提及任何有关重新声明的内容吗?(如果不在 cppreference 上,我实际上不确定官方 C++ 标准保存在哪里......)我是否需要像 C++ 中的其他内容一样担心概念的重新定义?
或者MSVC在这里错了?(并不是说我对 MSVC 能做很多事情...)搜索错误消息只得到了有关其他重新声明的信息,例如类和变量。显然“概念”对 SEO 不太友好。
Bar*_*rry 10
这个相当简单:根据 cppreference 文章,概念可以毫无问题地重新声明:
不,它没有这么说。这个片段:
template<Incrementable T>
void f(T) requires Decrementable<T>;
template<Incrementable T>
void f(T) requires Decrementable<T>; // OK, redeclaration
Run Code Online (Sandbox Code Playgroud)
不重新声明一个概念。它甚至没有声明一个概念。它显示的是两次声明相同的函数模板。该函数模板受到约束(同时具有Incrementable
和Decrementable
),但它仍然是一个函数模板。
你不能重新声明一个概念。
原因之一是你不能仅仅声明一个概念,你还必须定义它。你不能只写:
template <class T> concept C;
Run Code Online (Sandbox Code Playgroud)
以同样的方式你可以写:
template <class T> void f();
Run Code Online (Sandbox Code Playgroud)
f
这里只是函数模板的声明,我可以添加另一个声明。但只有一种定义。这是格式错误的:
template <class T> void f() { }
template <class T> void f() { }
Run Code Online (Sandbox Code Playgroud)
同样,这是格式错误的:
template <class T> concept C = true;
template <class T> concept C = true;
Run Code Online (Sandbox Code Playgroud)
只能有一个定义。