提问人:HolyBlackCat 提问时间:11/12/2023 更新时间:11/12/2023 访问量:64
我可以检查表达式是否与类型相关吗?
Can I check if an expression is type-dependent?
问:
有人告诉我答案是否定的,但我想我还是会问的。
我想在宏中检查特定表达式是否与类型相关。这里有一个激励人心的例子:
#include <concepts>
#include <format>
#include <iostream>
template <typename T>
void Print(const T &value)
{
if constexpr (std::default_initializable<std::formatter<T>>)
std::cout << std::format("{}", value) << '\n';
else
std::cout << "??\n";
}
#define PRINT(...) Print(__VA_ARGS__)
// ---
struct Unknown {};
template <typename T>
void MaybePrint(const T &value)
{
PRINT(value);
}
int main()
{
PRINT(42); // "42"
PRINT(Unknown{}); // "??", but I want a build error, because the expression is not type-dependent.
MaybePrint(42); // "42"
MaybePrint(Unknown{}); // "??", this is ok, since the expression is type-dependent.
}
我有一个宏,可以打印传递给它的任何对象(这是用于单元测试框架的)。
如果它不可打印,我显然想要一个编译错误。但是对于类型相关的表达式,我想要打印一个占位符(以避免每次都强制用户写入)。if constexpr (printable<T>) ...
答:
2赞
Patrick Roberts
11/12/2023
#1
将 的主体直接移动到宏中并调整约束可提供所需的行为:Print
#define PRINT(...) \
{ \
if constexpr (requires { \
std::formatter< \
std::remove_cvref_t<decltype(__VA_ARGS__)>>{}; \
}) \
std::cout << std::format("{}", __VA_ARGS__) << '\n'; \
else \
std::cout << "??\n"; \
}
struct Unknown {};
template <typename T>
void MaybePrint(const T &value) {
PRINT(value);
}
https://godbolt.org/z/4Po3xh9oP
我从 Clang 中删除了它,因为它似乎缺乏对此示例的库支持,但关于硬错误与替换失败的基本概念在 Clang 中的工作方式与在 GCC 和 MSVC 中的工作方式相同。-stdlib=libc++
正如 @SamVarshavchik 所指出的,您还可以将约束移动到函数参数以获得所需的行为:
template <class T>
concept printable = std::default_initializable<std::formatter<T>>;
void Print(const printable auto &value) {
std::cout << std::format("{}", value) << '\n';
}
struct Unknown {};
template <typename T>
void MaybePrint(const T &value) {
if constexpr (printable<T>) {
Print(value);
}
}
https://godbolt.org/z/1MzWhKzrM
评论
0赞
HolyBlackCat
11/12/2023
我什至不需要改变条件,似乎对我来说是有效的。if constexpr
1赞
Patrick Roberts
11/12/2023
@HolyBlackCat 使用原始约束时,如果在非依赖上下文中失败,GCC 仍会传递:godbolt.org/z/Thboe83d6PRINT
1赞
HolyBlackCat
11/12/2023
啊哈,我明白了。关于 in - 这是我想避免的事情,因为我不希望库用户手动编写它。if constexpr
MaybePrint
if constexpr
0赞
Patrick Roberts
11/12/2023
@HolyBlackCat啊,我只是想你可以提供一个 and 作为你图书馆的一部分。Print
MaybePrint
评论
requires
Print
T
if constexpr
std::formatter
static_assert
if constexpr
PRINT
template<typename T> concept printable = std::default_initializable<std::formatter<T>>;