static_assert 在具有非类型模板参数的函数模板中
static_assert in function template with non-type template parameter
我有一个带有整数模板参数的函数模板。我只想提供特定整数的实现。尝试将函数模板与另一个参数一起使用会导致编译错误。
我按照下面介绍的方式使用 static_assert
。
#include <type_traits>
#include <iostream>
template <typename T>
struct false_type : public std::false_type {};
template <int T>
void function() {
static_assert(false_type<decltype(T)>::value, "Error");
};
template <>
void function<1>() {
std::cout << 1 << std::endl;
}
int main() {
function<1>();
}
代码在 gcc 9.1
之前运行良好,它给出了 error: static assertion failed
.
我想知道是否有一种技术可以实现我的目标并且与 gcc 9.1
兼容?
我第一次回答这个问题时不明白原始代码有什么问题,但现在,感谢其他回答者,我明白了,所以这一切都是值得的。
无论如何,一个明显的解决方案是将您的三个模板替换为:
template <int T>
void function() {
static_assert(T == 1, "Error");
};
clang 和 MSVC 仍然成功编译了原始代码。
GCC 9.1 似乎认识到 false_type<decltype(T)>::value
并不真正依赖于 T
,这让它可以及早评估条件(当第一次看到模板时,而不是在实例化时)。
这是一个解决方法:
template <auto V, auto...> inline constexpr auto dependent_value = V;
template <int T>
void function()
{
static_assert(dependent_value<false, T>, "Error");
}
这样编译器必须实例化 function<T>
来评估 dependent_value<false, T>
(因为 dependent_value
可以在 之后专门化 [的定义=14=]).
请注意,由于无法为您的 function<int T>
实现生成有效的实例化,因此您问题中的代码是 ill-formed, no diagnostic required。
此变通方法没有此问题,因为您可以通过首先特化 dependent_value
来有效实例化 function<int T>
。
还有一个更简单的解决方案,不涉及 static_assert
:
template <int T> void function() = delete;
第一个参数是 non-dependent 假常量的 static_assert
始终是 "ill-formed, no diagnostic required",即使在从未实例化的模板中也是如此。 (所以这里 g++ 和 clang++ 都不是 "incorrect"。)在你的函数模板中,T
是 value-dependent 但不是 type-dependent (它的类型总是 int
),所以 decltype(T)
不依赖,false_type<int>::value
.
也不依赖
能否让您的 false_type
也简单地使用 int
作为参数?
#include <type_traits>
#include <iostream>
template <int>
struct false_type : public std::false_type {};
template <int T>
void function() {
static_assert(false_type<T>::value, "Error");
};
template <>
void function<1>() {
std::cout << 1 << std::endl;
}
int main() {
function<1>();
}
我有一个带有整数模板参数的函数模板。我只想提供特定整数的实现。尝试将函数模板与另一个参数一起使用会导致编译错误。
我按照下面介绍的方式使用 static_assert
。
#include <type_traits>
#include <iostream>
template <typename T>
struct false_type : public std::false_type {};
template <int T>
void function() {
static_assert(false_type<decltype(T)>::value, "Error");
};
template <>
void function<1>() {
std::cout << 1 << std::endl;
}
int main() {
function<1>();
}
代码在 gcc 9.1
之前运行良好,它给出了 error: static assertion failed
.
我想知道是否有一种技术可以实现我的目标并且与 gcc 9.1
兼容?
我第一次回答这个问题时不明白原始代码有什么问题,但现在,感谢其他回答者,我明白了,所以这一切都是值得的。
无论如何,一个明显的解决方案是将您的三个模板替换为:
template <int T>
void function() {
static_assert(T == 1, "Error");
};
clang 和 MSVC 仍然成功编译了原始代码。
GCC 9.1 似乎认识到 false_type<decltype(T)>::value
并不真正依赖于 T
,这让它可以及早评估条件(当第一次看到模板时,而不是在实例化时)。
这是一个解决方法:
template <auto V, auto...> inline constexpr auto dependent_value = V;
template <int T>
void function()
{
static_assert(dependent_value<false, T>, "Error");
}
这样编译器必须实例化 function<T>
来评估 dependent_value<false, T>
(因为 dependent_value
可以在 之后专门化 [的定义=14=]).
请注意,由于无法为您的 function<int T>
实现生成有效的实例化,因此您问题中的代码是 ill-formed, no diagnostic required。
此变通方法没有此问题,因为您可以通过首先特化 dependent_value
来有效实例化 function<int T>
。
还有一个更简单的解决方案,不涉及 static_assert
:
template <int T> void function() = delete;
第一个参数是 non-dependent 假常量的 static_assert
始终是 "ill-formed, no diagnostic required",即使在从未实例化的模板中也是如此。 (所以这里 g++ 和 clang++ 都不是 "incorrect"。)在你的函数模板中,T
是 value-dependent 但不是 type-dependent (它的类型总是 int
),所以 decltype(T)
不依赖,false_type<int>::value
.
能否让您的 false_type
也简单地使用 int
作为参数?
#include <type_traits>
#include <iostream>
template <int>
struct false_type : public std::false_type {};
template <int T>
void function() {
static_assert(false_type<T>::value, "Error");
};
template <>
void function<1>() {
std::cout << 1 << std::endl;
}
int main() {
function<1>();
}