如何让c++编译器区分std::function<void()>和std::function<asio::awaitable<void>()>参数?

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

在我的另一个问题中,我了解到

std::function<asio::awaitable<void>()>
可以自动转换为
std::function< void()>
。这会导致如下问题:

我需要编写一个具有两个重载的函数,它们接受两个回调:

std::function<asio::awaitable<void>()>
std::function<void()>
。根据上一个问题,很明显这是行不通的。

但是如果你将其更改为仅接受

std::function<void()>
类型的回调。虽然传入
std::function<asio::awaitable<void>()>
类型回调同样合法,但回调的真实返回值在函数内部不可用。

当然可以写成两个不同名称的函数。但问题依然存在,

std::function<void()>
的版本会导致非常容易误操作。因为即使你不小心通过了
std::function<asio::awaitable<void>
,编译器也不会报错。

对于如何解决上述问题有什么想法吗?

c++ std-function
1个回答
1
投票

在 C++20 中,您可以使用概念(或在 C++17 SFINEA 中)来“禁用”隐式类型转换,如下所示:

#include <functional>

namespace asio
{
template<typename type_t>
struct awaitable
{
};
}

template<typename signature_t>
concept VoidFunction = std::is_same_v<std::function<void()>,std::function<signature_t>>;

// use a concept or in C++ SFINEA to disable "implicit" type conversion
// now this function will only accept an explicit match
void func(auto VoidFunction /*cb*/)
{
}

void func(std::function<asio::awaitable<void>()> /*cb*/)
{
}

int main()
{
    func([]() -> asio::awaitable<void> {
       // co_return;
    });
}
© www.soinside.com 2019 - 2024. All rights reserved.