使用 c++20 概念传递参数化函数和参数列表

Pass parameterized function and list of parameters using c++20 Concepts

我有一个函数 foo 接受一个任意类型的参数,如下所示:

void foo(int& x)
{
    x = 4;
}

现在我想创建一个模板函数 bar,它接受一个带有 1 个参数的函数和一个参数列表来调用该函数。

template<typename Func, typename Params>
void bar(Func func, Params params)
{
     for(auto param : params)
     {
         func(param);
     }
}

这有效并编译,但我想改进它以使用 C++20 概念。首先,我创建了一个 iterable 概念,如下所示:

template<typename Container, typename ElementType>
concept iterable = std::ranges::range<Container> && std::same_as<typename std::iterator_traits<Container>::value_type, ElementType>;

并用它来检查迭代器的 value_type 是否与提供的容器的参数类型相同,如下所示:

template<typename Func, typename ParamType, typename Params>
requires std::invocable<Func, ParamType> && iterable<Params, ParamType>
void bar(Func func, Params params)
{
     for(auto param : params)
     {
         func(param);
     }
}

但是这个简单的例子无法编译

std::vector<int> payload(10, 5);
bar(&foo, payload);

出现以下错误信息

error C2672: 'bar': no matching overloaded function found
error C2783: 'void bar(Func,Params)': could not deduce template argument for 'ParamType'

这有点道理,因为 Func 和 Params 是函数的参数而 ParamType 不是,但我想解决这个问题而不必手动指定参数的类型。我还尝试将签名更改为 void bar(Func func, Params<ParamType> params) 或将模板更改为 ... typename ParamType, typename Params<ParamType>> 两者都没有编译。

如何在不显式指定 bar 的参数类型的情况下解决这个问题?

您可以使用标准库提供的工具来解决这个问题。您使用 input_rangeinvocable 概念,提供给定范围的 range_reference_t 类型作为调用函数的参数。

template<typename Func, std::ranges::input_range Rng>
  requires std::invocable<Func, std::ranges::range_reference_t<Rng>>
void bar(Func func, Rng params)
{
     for(auto &&param : params)
     {
         std::invoke(func, param);
     }
}