【问题标题】:How to pass a function template as a template argument?如何将函数模板作为模板参数传递?
【发布时间】:2021-08-05 11:20:40
【问题描述】:
#include <iostream>

template<typename... Args>
void print(Args const&... args)
{
    (std::cout << ... << args);
}

int main()
{
    std::cout << 1 << 2 << 3 << std::endl; // ok
    print(1, 2, 3);                        // ok
    print(1, 2, 3, std::endl);             // error! How to make it work?
}

online demo

如何将函数模板作为模板参数传递?

【问题讨论】:

  • 如果您使用print(1, 2, 3, std::endl&lt;char, std::char_traits&lt;char&gt;&gt;);,它会起作用,但您可能想要一种不必编写所有额外内容的方法。
  • 棘手...我可能会退回到'\n'(而不是std::endl)。
  • 就像@Scheff'sCat 所说,使用\nprint(1, 2, 3, '\n');,除非您绝对必须也刷新流。
  • 这不是 template 参数。

标签: c++ templates c++17 overloading overload-resolution


【解决方案1】:

其他 io 操作器也会遇到同样的问题,这些操作器通常是将流作为参数的函数,当它们是模板时。尽管您可以将它们包装在非模板可调用对象中:

#include <iostream>

template<typename... Args>
void print(Args const&... args)
{
    (std::cout << ... << args);
}
    
int main()
{
    std::cout << 1 << 2 << 3 << std::endl; // ok
    print(1, 2, 3);                        // ok
    print(1, 2, 3, [](std::ostream& o) -> std::ostream&{ 
               o << std::endl; 
               return o;
    });             // no error!
}

Output:

123
123123

语法相当繁重,所以你可能想使用辅助类型,虽然我会留给你写它(开玩笑,我不认为这是微不足道的,但我可能会稍后尝试;)。思考了一会儿,我几乎可以肯定只有两个选择:实例化函数(参见other answer),或者将调用包装在 lambda 中,除非您想为每个单独的 io 操纵器编写一个包装器当然。

【讨论】:

    【解决方案2】:

    这里有一个方法:

    print(1, 2, 3, std::endl<char, std::char_traits<char>>);
    

    考虑改用'\n'

    【讨论】:

    【解决方案3】:

    您不能获取大多数标准函数的地址(请参阅can-i-take-the-address-of-a-function-defined-in-standard-library)。

    幸运的是,io-manipulator 是异常的一部分(参见Addressable_functions)。

    std::endl 是一个模板函数,因此您必须选择正确的重载。

    using print_manip_t = std::ostream& (*) (std::ostream&);
    
    print(1, 2, 3, print_manip_t{std::endl});
    print(1, 2, 3, static_cast<print_manip_t>(std::endl));
    print(1, 2, 3, static_cast<std::ostream& (*) (std::ostream&)>(std::endl));
    

    否则你必须指定你想要哪一个

    print(1, 2, 3, std::endl<char, std::char_traits<char>>);
    

    或者包装一下

    print(1, 2, 3, [](std::ostream& o) -> std::ostream&{ return o << std::endl; });
    

    Demo

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-14
    • 1970-01-01
    • 2014-08-02
    • 2012-12-27
    • 2017-06-14
    • 2019-11-16
    • 1970-01-01
    相关资源
    最近更新 更多