不带任意参数的c++函数模板
c++ function templates with not arbitrary parameters
考虑下面的c++代码:
template <size_t N>
int check(std::array<unsigned char, N> buf){
std::cout << N << "-" << buf.size() << std::endl;
return 0;
}
int main (int argc, char *argv[])
{
std::array<unsigned char, 20> a;
std::array<unsigned char, 30> b;
std::array<unsigned char, 40> c;
check(a);
check(b);
check(c);
return 0;
}
是否有可能为N=20和N=30显式实例化"check",但禁用任何其他隐式实例化?
这意味着我想得到一个编译时错误,如果我使用"check(c)",
编辑:实际上我想要有相同的实现,所以模板是正确的选择,如果由于某种原因我用一个不应该存在的参数实例化它,我只想有一个编译时错误。因此,static_assert (c++11)解决方案看起来是最好的,因为它完整地解决了这个问题,并且非常易于人类阅读。
如果N
不是20或30,可以使用static_assert
抛出编译时错误。
template <size_t N>
int check(std::array<unsigned char, N> buf)
{
static_assert(N == 20 || N == 30, "N must be 20 or 30.");
std::cout << N << "-" << buf.size() << std::endl;
return 0;
}
您可以使用static_assert
:
template <size_t N>
int check(std::array<unsigned char, N> buf){
static_assert(N==20 || N==30, "invalid value of N");
std::cout << N << "-" << buf.size() << std::endl;
return 0;
}
如果N
的值无效,将导致编译时错误。现场观看
有几种方法可以做到这一点。
一种方法是:
template <size_t N>
typename std::enable_if<N == 20 || N == 30, int>::type
check(std::array<unsigned char, N> buf) {
//..
}
关于在这个和static_assert
之间选择的一些想法,在其他答案中显示:
-
static_assert
可能被一些人视为比enable_if
更干净,更清楚地表达约束的方式。 - (我认为最重要的区别):这种方式约束是函数接口的一部分,即函数的定义表达约束。
static_assert
是实现的一部分。在更复杂的代码中,这甚至会影响函数重载的方式。 - 与
static_assert
你得到一个明确的消息是什么是错误的约束不满足。
另一种方法是删除函数:
template <size_t N>
void check(std::array<unsigned char, N> buf) = delete;
void check(std::array<unsigned char, 20> buf)
{
std::cout << 20 << "-" << buf.size() << std::endl;
}
void check(std::array<unsigned char, 30> buf)
{
std::cout << 30 << "-" << buf.size() << std::endl;
}
生活例子
如果以不同的方式处理数组,则模板在您的情况下是无用的。只需提供一些重载:
#include <array>
#include <iostream>
int check(std::array<unsigned char, 20> buf){
std::cout << "Handling an array of size 20n";
return 0;
}
int check(std::array<unsigned char, 30> buf){
std::cout << "Handling an array of size 30n";
return 0;
}
int check(std::array<unsigned char, 40> buf){
std::cout << "Handling an array of size 40n";
return 0;
}
int main (int argc, char *argv[])
{
std::array<unsigned char, 20> a;
std::array<unsigned char, 30> b;
std::array<unsigned char, 40> c;
check(a);
check(b);
check(c);
// std::array<unsigned char, 0> d;
//error: no matching function for call to ‘check(std::array<unsigned char, 0ul>&)'
//check(d);
return 0;
}
否则,如果代码相同,则使用static_assert是不错的选择(参见@Joachim Pileborg注释)
相关文章:
- 当函数模板参数是具有默认参数的类模板时,函数模板参数的推导如何执行
- 将重载的成员函数传递给函数模板
- C++17中函数模板中的静态数组初始化(MSVC 2019)
- 为什么 gcc 和 clang 为函数模板的实例化生成不同的符号名称?
- 具有常量引用参数的函数模板专用化
- std::span<const T> 作为函数模板中的参数
- 如何编写一个完美的缩写函数模板?
- 仅在函数模板中为那些定义了函数的类型执行函数
- 如何在C++中伪造虚拟可变参数函数模板?
- 以下代码中的函数模板有什么问题?
- 在 C++20 中是否不再允许在 std 中对程序定义类型的函数模板进行专用化?
- 将显式实例化的函数模板与转换匹配
- 使用定义函数模板别名
- 函数模板返回类型
- C++有什么方法可以在既不调用函数模板也不提供其模板参数的情况下引用函数模板?
- C++ std::functional 中的可变参数函数模板
- 单行函数模板 c++ 的内联性保证
- C++函数模板需要 &for 数组参数
- 概念解析为使用 std::make_signed_t 时意外的函数模板
- 两个函数模板候选项.将一个参数作为引用后,选择不太专业的模板