我有一个带有整数模板参数的功能模板。我只想提供特定整数的实现。尝试将函数模板与其他参数一起使用会导致编译错误。
我以下面介绍的方式使用了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
兼容?
答案 0 :(得分:4)
一个static_assert
的第一个参数是不相关的虚假常量,即使在从未实例化的模板中,也始终“格式错误,无需诊断”。 (因此,这里的g ++和clang ++都不是“不正确的”。)在您的函数模板中,T
与值相关,但与类型无关(其类型始终为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>();
}
答案 1 :(得分:2)
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
可以在function<T>
的定义之后
请注意,由于无法为实现function<int T>
生成有效的实例化,因此问题中的代码为ill-formed, no diagnostic required。
此解决方法不存在此问题,因为您可以通过先专门设置function<int T>
来制作dependent_value
的有效实例。
还有一个不涉及static_assert
的简单解决方案:
template <int T> void function() = delete;
答案 2 :(得分:1)
当我第一次回答这个问题时,我不明白原始代码是什么问题,但是现在,由于其他答复者,我做到了,所以这一切都值得。
无论如何,一个显而易见的解决方案是将三个模板替换为:
template <int T>
void function() {
static_assert(T == 1, "Error");
};
clang和MSVC仍然可以成功地编译原始代码。