将 lambda 传递给具有推导类型的模板化函数

问题描述 投票:0回答:1

我有以下示例,其中包含两个版本的 make 函数,它们接受另一个函数并推导参数类型。然后它使用该函数创建模板化 Signature 类型的结构。

enum class SomeEnum {
     ONE = 1,
     TWO = 2,
};

template <SomeEnum _Type, typename _Result, typename... _Args>
struct Signature {
  static constexpr SomeEnum Type = _Type;
  using Result = _Result;
  using Args = std::tuple<_Args...>;

  std::function<_Result (_Args...)> func;
};

template <
    SomeEnum _Type,
    typename _Result,
    typename... _Args>
Signature<_Type, _Result, _Args...> make(
    std::function<_Result (_Args...)> func) {
  return Signature<_Type, _Result, _Args...>{.func = func};
}

template <SomeEnum _Type, typename _Result, typename... _Args>
Signature<_Type, _Result, _Args...> make(
    _Result (*func)(_Args...)) {
  return Signature<_Type, _Result, _Args...>{
      .func = std::move(func)};
}

void foo(int x, std::string y, int z) {
}

auto sig1 = make<SomeEnum::ONE>(&foo);

auto sig2 = make<SomeEnum::TWO>([](int x, std::string y, int z) {
});

此版本有效:

auto sig1 = make<SomeEnum::ONE>(&foo);

但是这个版本:

auto sig2 = make<SomeEnum::TWO>([](int x, std::string y, int z) {
});

没有

main.cpp:40:13: error: no matching function for call to 'make'
auto sig2 = make<SomeEnum::TWO>([](int x, std::string y, int z) {
            ^~~~~~~~~~~~~~~~~~~
main.cpp:23:37: note: candidate template ignored: could not match 'std::function<_Result (_Args...)>' against '(lambda at main.cpp:40:33)'
Signature<_Type, _Result, _Args...> make(
                                    ^
main.cpp:29:37: note: candidate template ignored: could not match '_Result (*)(_Args...)' against '(lambda at main.cpp:40:33)'
Signature<_Type, _Result, _Args...> make(
                                    ^
1 error generated.

但是,如果我明确设置类型,那么它就可以工作:

std::function<void(int x, std::string y, int z)> l = [](int x, std::string y, int z) {
};

auto sig2 = make<SomeEnum::TWO>(l);

我怎样才能制作这个版本:

auto sig2 = make<SomeEnum::TWO>([](int x, std::string y, int z) {
});

工作?我希望能够通过额外的输入来传递 lambda,并让代码推导出类型。

c++ templates lambda
1个回答
0
投票

std::function
支持 CTAD(通过其推导指南),但 CTAD 不适用于函数参数。

所以你的参数类型必须是模板化的(而不是

std::function<__>
):

template <typename F> void foo(F &&func) {bar(std::function(func));}

其中

bar
接受
std::function<R(P...)>
,就像您第一次重载
make()

© www.soinside.com 2019 - 2024. All rights reserved.