是否可以在 C++ 中扣除模板参数的模板类型?

Is it possible to deduct the template type of a templated parameter in C++?

我有一个模板 class,其内部方法本身就是模板。

考虑以下最小工作示例

#include <functional>

template<typename T>
class P{
public:
    template <typename U>
    P<U> call(std::function< P<U> (T)> f){
        return f(return_value);
    }
    T return_value;
};

P<int> foo() {
    P<int> value = P<int>();
    return value;
}

P<float> bar(int arg) {
    return P<float>();
}

int main()
{
    auto res = foo().call<float>(bar);

    return 0;
}

正如您在 main 函数中看到的那样,编译器强制我指定 float 类型来调用 call() 函数,尽管传递 [=] 时该类型应该很明显14=] 函数,指定 float 类型。

是否可以通过某种方式推导类型,使main函数中的代码可以简化为如下语句:

auto res = foo().call(bar);

std::function 不是您想要传递函数时应该使用的类型。 std::function 是一种使用类型擦除能够将不同类型的可调用对象存储在一个类型中的类型。如果你不需要那个,那么你不需要 std::function:

#include <functional>

template<typename T>
class P{
public:
    template <typename F>
    auto call(F f){
        return f(return_value);
    }
    T return_value{};  // don't forget to initialize !
};

P<int> foo() {
    P<int> value = P<int>();
    return value;
}

P<float> bar(int arg) {
    return P<float>();
}

int main()
{
    auto res = foo().call(bar);

    return 0;
}

使用部分特化,您可以获得 bar 的 return 类型,并且可以从 P<float>:

获得 float
#include <type_traits>
#include <iostream>

template <typename T> class P;

// get return type from function
template <typename T> struct return_type;

template <typename R,typename...args>
struct return_type<R(args...)> { using type = R; };

// get T from P<T>
template <typename P> struct P_arg;   
template <typename T> struct P_arg< P<T> > { using type = T; };

// combine both
template <typename F>
struct get {
    using type = typename P_arg<typename return_type<F>::type >::type;
};

template<typename T>
class P{
public:
    template <typename F>
    auto call(F f){
        return f(return_value);
    }
    T return_value{};
};

P<float> bar(int arg) {
    return P<float>();
}

int main()
{
    std::cout << std::is_same_v< get<decltype(bar)>::type,float>;
    return 0;
}

虽然这在这里并没有真正帮助,因为你不能用它来装饰 P::call 的 return 类型,因为它需要 P<float> 已经完成。