如果 `if constexpr` 不匹配则停止编译
Stop compilation if `if constexpr` does not match
我有一个模板函数,它使用 if constexpr
检查模板参数的类型,例如
template <typename T>
bool something(T arg) {
if constexpr (std::is_integral_v<T>) {
return true;
} else {
// What can I write here so that something<double>(0.0) does not compile?
}
return false;
}
如果我的 if constexpr
中的 none 匹配,我怎样才能使代码编译失败?
解决方法是使用static_assert
.
但我们不能简单地在 else
分支中执行 static_assert(false, "whatever");
,因为由于条件不依赖于模板参数,断言可能会提前触发(当编译器第一次看到你的函数体,即使 else
分支实际上从未被采用过)。
static_assert
的条件必须以某种方式依赖于 T
,以延迟断言检查,直到您的模板被实例化。
这是我一直在使用的:
template <auto A, typename...> auto value = A;
if constexpr (foo)
{
...
}
else if constexpr (bar)
{
...
}
else
{
static_assert(value<false, T>, "Invalid template parameter.");
}
请注意,如果您只有 一个 if constexpr
(而不是 if
else if
链),则 none需要其中的一部分。
只需将条件从 if
移动到 static_assert
并删除 if
.
再补充一个答案,虽然思路是一样的。
你可以在你的 else 分支中使用它:
static_assert(!std::is_same_v<T,T>, "")
可读性有点差,但它确实有效:)
我也有同样的疑问
我不是专家,但这对我有用,不需要任何额外的定义。
static_assert(! std::is_void<std::void_t<T>>::value , "")
首先,std::void_t<T>
对于任何 T 总是 returnsvoid 类型。
然后,如果 T 为空,std::is_void<T>::value
为真。
所以这是一种从任何类型 T.
获取 true/false 的方法
应该从 C++17 开始工作。
我有一个模板函数,它使用 if constexpr
检查模板参数的类型,例如
template <typename T>
bool something(T arg) {
if constexpr (std::is_integral_v<T>) {
return true;
} else {
// What can I write here so that something<double>(0.0) does not compile?
}
return false;
}
如果我的 if constexpr
中的 none 匹配,我怎样才能使代码编译失败?
解决方法是使用static_assert
.
但我们不能简单地在 else
分支中执行 static_assert(false, "whatever");
,因为由于条件不依赖于模板参数,断言可能会提前触发(当编译器第一次看到你的函数体,即使 else
分支实际上从未被采用过)。
static_assert
的条件必须以某种方式依赖于 T
,以延迟断言检查,直到您的模板被实例化。
这是我一直在使用的:
template <auto A, typename...> auto value = A;
if constexpr (foo)
{
...
}
else if constexpr (bar)
{
...
}
else
{
static_assert(value<false, T>, "Invalid template parameter.");
}
请注意,如果您只有 一个 if constexpr
(而不是 if
else if
链),则 none需要其中的一部分。
只需将条件从 if
移动到 static_assert
并删除 if
.
再补充一个答案,虽然思路是一样的。
你可以在你的 else 分支中使用它:
static_assert(!std::is_same_v<T,T>, "")
可读性有点差,但它确实有效:)
我也有同样的疑问
我不是专家,但这对我有用,不需要任何额外的定义。
static_assert(! std::is_void<std::void_t<T>>::value , "")
首先,std::void_t<T>
对于任何 T 总是 returnsvoid 类型。
然后,如果 T 为空,std::is_void<T>::value
为真。
所以这是一种从任何类型 T.
应该从 C++17 开始工作。