将 lambda(int)->int 转换为 std::function<int(float)>
Converting lambda(int)->int to std::function<int(float)>
为什么 C++ 编译器不针对此代码给出警告或错误?
std::function<int(float)> f = [](int x) -> int {
return x*x;
};
std::cout << f(4.2) << '\n';
有没有办法防止这种含蓄的对话? (例如编写包装器或辅助方法以生成错误)
Why C++ compiler doesn't give warning or error for this code?
针对此类情况的 gcc 编译器选项通常是 -Wconversion
,但它似乎不适用于您的特定情况。我尝试了很多其他标志但没有成功。但是,您可以使用 MSVC 获得警告级别 4 的综合警告。
为什么会报错?这将与 std::function
的一个主要目的相矛盾,即从允许的隐式转换中获益,以保持作为一般函子持有者的灵活性,并且有疑问,您可以通过签名自行使事情变得更加明确检查器特征。对于 std::function
,它可能看起来像这样(“旧的”C++17 之前的方法,通用 Lambda 和重载的一些缺点,请参阅评论):
template <typename ProvidedSignature, typename RequiredSignature>
struct SignatureMatches : std::false_type
{};
template <typename R1, typename R2>
struct SignatureMatches<R1(), R2()> : std::is_convertible<R2, R1>
{};
template <typename R1, typename R2, typename Arg1, typename Arg2, typename... Args1, typename... Args2>
struct SignatureMatches<R1(Arg1, Args1...), R2(Arg2, Args2...)>
: std::conditional_t<
std::is_convertible_v<std::remove_cv_t<std::remove_reference_t<Arg1>>, std::remove_cv_t<std::remove_reference_t<Arg2>>>,
SignatureMatches<R1(Args1...), R2(Args2...)>,
std::false_type>
{};
template <typename R1, typename R2, typename... Args1, typename... Args2>
struct SignatureMatches<R1(Args1...) noexcept, R2(Args2...) noexcept>
: SignatureMatches<R1(Args1...), R2(Args2...)>
{};
为了您自己的目的,您只需更改
std::is_convertible_v<std::remove_cv_t<std::remove_reference_t<Arg1>>, std::remove_cv_t<std::remove_reference_t<Arg2>>>
更严格的方案,可能通过 std::is_same
。
另请参阅标准对可调用对象的定义和要求:Callable
为什么 C++ 编译器不针对此代码给出警告或错误?
std::function<int(float)> f = [](int x) -> int {
return x*x;
};
std::cout << f(4.2) << '\n';
有没有办法防止这种含蓄的对话? (例如编写包装器或辅助方法以生成错误)
Why C++ compiler doesn't give warning or error for this code?
针对此类情况的 gcc 编译器选项通常是 -Wconversion
,但它似乎不适用于您的特定情况。我尝试了很多其他标志但没有成功。但是,您可以使用 MSVC 获得警告级别 4 的综合警告。
为什么会报错?这将与 std::function
的一个主要目的相矛盾,即从允许的隐式转换中获益,以保持作为一般函子持有者的灵活性,并且有疑问,您可以通过签名自行使事情变得更加明确检查器特征。对于 std::function
,它可能看起来像这样(“旧的”C++17 之前的方法,通用 Lambda 和重载的一些缺点,请参阅评论):
template <typename ProvidedSignature, typename RequiredSignature>
struct SignatureMatches : std::false_type
{};
template <typename R1, typename R2>
struct SignatureMatches<R1(), R2()> : std::is_convertible<R2, R1>
{};
template <typename R1, typename R2, typename Arg1, typename Arg2, typename... Args1, typename... Args2>
struct SignatureMatches<R1(Arg1, Args1...), R2(Arg2, Args2...)>
: std::conditional_t<
std::is_convertible_v<std::remove_cv_t<std::remove_reference_t<Arg1>>, std::remove_cv_t<std::remove_reference_t<Arg2>>>,
SignatureMatches<R1(Args1...), R2(Args2...)>,
std::false_type>
{};
template <typename R1, typename R2, typename... Args1, typename... Args2>
struct SignatureMatches<R1(Args1...) noexcept, R2(Args2...) noexcept>
: SignatureMatches<R1(Args1...), R2(Args2...)>
{};
为了您自己的目的,您只需更改
std::is_convertible_v<std::remove_cv_t<std::remove_reference_t<Arg1>>, std::remove_cv_t<std::remove_reference_t<Arg2>>>
更严格的方案,可能通过 std::is_same
。
另请参阅标准对可调用对象的定义和要求:Callable