不带任意参数的c++函数模板

c++ function templates with not arbitrary parameters

本文关键字:c++ 函数模板 参数 任意      更新时间:2023-10-16

考虑下面的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注释)