使用可变参数模板帮助程序进行多个 std::variant 访问

Hur*_*ent 8 c++ templates variadic-templates c++17

我正在尝试创建一个有助于处理 Nstd::variant类型的函数。

注意:我正在尝试验证所有路径的编译时间。所以std::optionalstd::holds_alternative不可行我。

实现如下:

template<typename T>
using Possible = std::variant<std::monostate, T>;

template<typename... Types>
void ifAll(std::function<void(Types...)> all, Possible<Types>&&... possibles)
{
    std::visit(
        [&](auto&&... args) {
            if constexpr ((... &&
                           std::is_same_v<std::decay_t<decltype(args)>, Types>))
            {
                return all(std::forward<Types>(args)...);
            }
            else
            {
                std::cout << "At least one type is monostate" << std::endl;
            }
        },
        possibles...);
}
Run Code Online (Sandbox Code Playgroud)

使用该函数的一个例子是:

int main()
{
    Possible<int>  a = 16;
    Possible<bool> b = true;

    ifAll([](const int& x, const bool& y)
              -> void { std::cout << "All types set!" << std::endl; },
          a,
          b);
}
Run Code Online (Sandbox Code Playgroud)

但是我收到一个编译器错误:

TestFile.cc: error: no matching function for call to 'ifAll'
    ifAll([](const int& x, const bool& y)
    ^~~~~

TestFile.cc: note: candidate template ignored: could not match
    'function<void (type-parameter-0-0...)>' against '(lambda at
    TestFile.cc)'

void ifAll(std::function<void(Types...)> all, Possible<Types>&&... possibles)
    ^
Run Code Online (Sandbox Code Playgroud)

为什么我提供的 lambda 与函数签名不匹配?

尝试修复 1

我尝试搬进去ab但仍然不起作用:

ifAll([](const int& x, const bool& y)
              -> void { std::cout << "All types set!" << std::endl; },
          std::move(a),
          std::move(b));
Run Code Online (Sandbox Code Playgroud)

Nut*_*ker 4

以下调用可以工作:

int main() {
    Possible<int>  a = 16;
    Possible<bool> b = true;

    std::function<void(int, bool)> fun = [](int x, bool y) -> void {
        std::cout << "All types set!" << std::endl;
    };

    ifAll(fun,
          std::move(a),
          std::move(b));
}
Run Code Online (Sandbox Code Playgroud)

或将您的函数签名切换为:

template <typename... Types>
void ifAll(std::function<void(Types...)> const& all, Possible<Types>&... possibles)
Run Code Online (Sandbox Code Playgroud)

然后你就可以调用它而无需std::move

int main() {
    Possible<int>  a = 16;
    Possible<bool> b = true;

    std::function<void(int, bool)> fun = [](int x, bool y) -> void {
        std::cout << "All types set!" << std::endl;
    };

    ifAll(fun, a, b);
}
Run Code Online (Sandbox Code Playgroud)