传递重载函数指针及其参数时的错误类型推导

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

我正在尝试在std::invoke周围提供包装器,以进行推导函数类型的工作,即使函数已重载也是如此。(我昨天向related question询问了可变参数和方法指针的版本。)>

[当函数具有一个参数时,此代码(C ++ 17)在正常的重载条件下可以正常工作:

#include <functional>

template <typename ReturnType, typename ... Args>
using FunctionType = ReturnType (*)(Args...);

template <typename S, typename T>
auto Invoke (FunctionType<S, T> func, T arg)
{   
    return std::invoke(func, arg);
}

template <typename S, typename T>
auto Invoke (FunctionType<S, T&> func, T & arg)
{   
    return std::invoke(func, arg);
}

template <typename S, typename T>
auto Invoke (FunctionType<S, const T&> func, const T & arg)
{
    return std::invoke(func, arg);
}

template <typename S, typename T>
auto Invoke (FunctionType<S, T&&> func, T && arg)
{   
    return std::invoke(func, std::move(arg));
}

显然,减少更多输入参数的代码膨胀,但这是一个单独的问题。

如果用户的重载仅因const /引用而不同,例如:

#include <iostream>

void Foo (int &)
{
    std::cout << "(int &)" << std::endl;
}

void Foo (const int &)
{
    std::cout << "(const int &)" << std::endl;
}

void Foo (int &&)
{
    std::cout << "(int &&)" << std::endl;
}

int main()
{
    int num;
    Foo(num);
    Invoke(&Foo, num);

    std::cout << std::endl;

    Foo(0);
    Invoke(&Foo, 0);
}

然后Invoke用g ++输出错误地推导了该函数:

(int&)(const int&)

(int &&)(const int&)

和clang ++:

(int&)(const int&)

(int &&)(int &&)

(感谢geza指出clang的输出是不同的。

所以Invoke具有未定义的行为。

我怀疑元编程将是解决此问题的方法。无论如何,是否可以在Invoke站点正确处理类型推导?

我正试图在std :: invoke周围提供一个包装器,以进行推导函数类型的工作,即使函数被重载也是如此。 (我昨天问了一个有关可变参数和方法的相关问题...

c++ templates function-pointers template-meta-programming type-deduction
1个回答
0
投票

理论

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