我们可以使用可变参数模板函数来过滤特定类型的参数,然后将其余的函数传递给另一个函数吗?

P.X*_*P.X 9 c++ templates variadic-templates c++11

例如

// we have a variadic function
void print(...);    

// I need such a function to filter parameters of specific type
template<typename... Args>
void print_filter(const Args&... args)
{
    // filter non-integral type
    print(integral args);
}

// my goal, all non-integral type can be ignored:
print_filter(1.0, 2, "abc", 3) == print(2, 3)
Run Code Online (Sandbox Code Playgroud)

我已经用尽了我的知识......你能帮忙吗?或者只是为了证明这是不可能的,这也是非常有帮助的.谢谢

eca*_*mur 5

一个巧妙的技巧是将您想要的参数转换为 1 元素转发元组,将您不想要的参数转换为空元组,tuple_cat结果,然后apply(C++17) 将结果元组转换为您想要调用的函数:

template<typename... Args>
void print_filter(Args&&... args) {
    std::apply(
        [](auto&&... args) { return print(std::forward<decltype(args)>(args)...); },
        std::tuple_cat(
            std::get<std::is_integral<typename std::decay<Args>::type>::value ? 0 : 1>(
                std::make_tuple(
                    [](Args&& arg) { return std::tuple<Args&&>{std::forward<Args>(arg)}; },
                    [](Args&&) { return std::tuple<>{}; }))(
                std::forward<Args>(args))...));
}
Run Code Online (Sandbox Code Playgroud)

请注意,这使用了另一个技巧,即get用于有条件地将两个函数之一应用于参数。

例子。


Atn*_*nNn 1

这是一种方法。首先创建一个虚拟分隔符类:

class SEP { };
Run Code Online (Sandbox Code Playgroud)

然后,一个辅助函数通过将其他参数推到参数列表的末尾来丢弃所有非整数参数:

template <class T, class... R>
void print_filter_(T x, R... a) {
  if (std::is_integral<T>::value) {
    print_filter_(a..., x);
  } else {
    print_filter_(a...);
  }
}
Run Code Online (Sandbox Code Playgroud)

在检查完所有初始参数后,只剩下整数参数:

template <class... T>
void print_filter_(SEP, T... a) {
  print(a...);
}
Run Code Online (Sandbox Code Playgroud)

最后,调用辅助函数:

template <class... T>
void print_filter(T... a) {
  print_filter_(a..., SEP());
}
Run Code Online (Sandbox Code Playgroud)