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

How to pass a function template as a template argument?

#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<char, std::char_traits<char>>);

考虑改用 '\n'

您将遇到与其他 io 操纵器相同的问题,这些 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

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

您不能获取大多数标准函数的地址(参见 )。

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

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

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