使用带有std :: optional参数的std :: function重载歧义

Inn*_*der 6 c++ c++17

这是一个简单的示例程序:

using fn_string = function<void(const string&)>;
using fn_optional_string = function<void(const optional<string>&)>;

void foo(fn_string) { cout << "string" << endl; }
void foo(fn_optional_string) { cout << "optional string" << endl; }

int main()
{
    foo([&](const string&){ });
    foo([&](const optional<string>&){ }); // <-- ambiguous
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

它有2个重载foo()- 一个带string参数函数,另一个带函数optional<string>.

为什么第二次呼叫foo()模棱两可?

有没有一种简单的方法来解决它?没有演员阵容?

UPDATE

以上是我试图解决的以下现实世界问题的过度简化示例,即:

using delegate = variant<
    function<void()>,
    function<void(const string&)>,
    function<void(const optional<string>&)>
>;

struct foo
{
    void add_delegate(delegate fn) { fns.push_back(std::move(fn)); }
    vector<delegate> fns;
};

int main()
{
    foo bar;
    bar.add_delegate([&](){ });
    bar.add_delegate([&](const string&){ });
    bar.add_delegate([&](const optional<string>&){ }); // ERROR
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

最后一次调用add_delegate无法编译,因为它无法在function<void(const string&)>和之间做出决定function<void(const optional<string>&)>.

我的理解是这个问题与重载决策有关(因此我的原始例子).我应该做些什么改变add_delegate以允许它接受所有3个版本的lambdas?

完整的例子可以在Coliru找到.

Inn*_*der 0

嗯,结果比我想象的要简单。我所要做的就是添加以下重载struct foo

void add_delegate(fn_opt_val fn) { add_delegate(delegate{ std::move(fn) }); }
Run Code Online (Sandbox Code Playgroud)

这是Coliru的完整代码。