关于ints的专业化,和static_assert
我想写一个模板函数,只能用于2个数字(例如3和5),并给出错误,如果你尝试使用它与另一个数字。关于ints的专业化,和static_assert
我可以这样做:
template<int x>
void f();
template<>
void f<3>()
{
cout << "f<3>()\n";
}
template<>
void f<5>()
{
cout << "f<5>()\n";
}
,然后我可以调用这个函数的正常方式:
f<3>();
f<5>();
并将其编译好了,如果我尝试使用我的功能不正确:
f<10>();
编译器给我一个错误。
我有这个方法的2个问题:
1.-是这个标准吗?我可以用ints专门设计一个模板吗?
2.-如果你使用这种方法,我不喜欢你得到的错误,因为错误不会告诉用户他错误地做了什么。我更喜欢写这样的东西:
template<int x>
void f()
{
static_assert(false, "You are trying to use f with the wrong numbers");
}
但这不能编译。看来我的编译器(gcc 5.4.0)试图首先实例化主模板,并且因为它提供了错误(static_assert)。
谢谢你的帮助。
如果你想知道为什么我想这样做,是因为我正在学习如何编程一个微控制器。在微控制器中,你有一些只能做一些事情的引脚。例如,引脚3和5是可以产生方波的引脚。如果一个应用程序,我想产生方波,我想写的财产以后,如:
square_wave<3>(frecuency);
但是,如果几个月后,我想重用这个代码(或修改)在另一个应用程序与differente微控制器,我想我的编译器对我说:“呃,在这个微控制器中,你不能在引脚3和5上产生方波,而是使用引脚7和9”。我认为这可以为我节省很多麻烦(或者不是,我真的不知道,我只是在学习如何编程一个微控制器)。
static_assert
的条件始终为false
,这使得在选择规范之前无法在重载分辨率中选择主模板。您可以根据tempalate参数x
更改static_assert
的条件。 .eg
template<int x>
void f()
{
static_assert(x == 3 || x == 5, "You are trying to use f with the wrong numbers");
}
从标准,$17.7/8,9 Name resolution [temp.res]:
紧随其定义模板的假设实例将由于不良形成不依赖于结构模板参数
...
否则,对于可以生成有效专业化的模板,不得发布诊断。
和$17.7.2/1 Dependent names [temp.dep]:
里面一个模板,一些结构有可能不同从一个实例到另一个语义。这样的结构取决于模板参数。
好吧,但它很hacky。为什么不''删除''功能呢? – Rakete1111
@ Rakete1111因为OP想要一些更明确的定制信息。 – songyuanyao
我想他们只是想要一个编译器错误,而不是一个链接器。但是没问题 :) – Rakete1111
1.-是否是标准?我可以用ints专门设计一个模板吗?
是的。
2.
template<int x>
void f()
{
static_assert(false, "You are trying to use f with the wrong numbers");
}
你需要改变静态断言条件到的东西,是依赖于模板参数的值。一些简单的事情
template <int x>
void f()
{
static_assert(x - x, "You are trying to use f with the wrong numbers");
}
应该工作。
顺便说一句,这是值得注意的是,它通常被认为不是一个好主意,专门函数模板,为一体的专业化交互严重(或至少有点不可预知)与函数重载。因此,它可能是一个更好的主意,一般用一个函数对象来代替:
template <int I>
struct do_f {
static_assert(I - I, "You are trying to use f with the wrong numbers");
};
template <>
struct do_f<3> {
void operator()(args...) { ... }
};
template <>
struct do_f<5> {
void operator()(args...) { ... }
};
然后你就可以编写调用该函数对象的包装功能:
template <int I>
void f(args...) {
do_f<I>{}(args...);
}
其他的答案只有建议解决方法。尤其是因为它涉及编写一些样板代码。最容易做的事情是
template<int x>
void f() = delete;
然后你会得到像
error: call to deleted function 'f'
一个很好的编译器错误当您尝试实例化一个非专业int
模板。
#include <iostream>
template<int x>
void f() = delete;
template<>
void f<3>()
{
std::cout << "f<3>()\n";
}
template<>
void f<5>()
{
std::cout << "f<5>()\n";
}
int main()
{
f<3>();
f<5>();
f<10>(); // BOOM!
}
“_but这并不compile_” 什么是编译错误?用哪个测试? ''f ()''不应该使用静态断言进行编译。 – nefas
@nefas它不能用_any_值的'x'进行编译。 –