繁体   English   中英

没有任意参数的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(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) {
  //..
}

关于在其他答案中显示的this和static_assert之间进行选择的一些想法:

  • enable_if相比, static_assert可能被视为表达约束的更简洁明了的方式
  • (我认为最重要的区别):这样,约束成为函数接口的一部分,即函数的定义表示约束。 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 20\n";
    return 0;
}

int check(std::array<unsigned char, 30> buf){
    std::cout << "Handling an array of size 30\n";
    return 0;
}
int check(std::array<unsigned char, 40> buf){
    std::cout << "Handling an array of size 40\n";
    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评论)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM