为什么这个 `my::test` 没有推导出模板参数?

Why is this `my::test` not deduced template parameter?

我遇到了与此类似的问题:std::function and std::bind: how to load a std::bind with a function template

我没有找到任何满意的答案,但我的疑问与上述post相似(不相同)

代码:

#include <iostream>
#include <functional>

using namespace std;

namespace my {
  template <typename T>
  struct test;

  template <typename R, typename ...Ts>
  struct test<R(Ts...)>{    
    test(R(*func)(Ts...)){
       //None content, only test
    }
  };
}

void install1(my::test<int(int, int)> func)
{

}

template <typename R, typename ...Ts>
void install2(my::test<R(Ts...)> func)
{

}

int add(int a, int b)
{
    return a + b;
}

int main(int argc, char *argv[])
{

    install1(add);

    my::test<int(int, int)> fun = add;
    install1(fun);

    install2<int, int, int>(add);

    return 0;
}

我注意到的问题:

在此先感谢,对于问题描述中的任何误解,我深表歉意(我使用的是google翻译)

template <typename R, typename ...Ts>
void install2(my::test<R(Ts...)> func)

并打电话

install2<int, int, int>(add);

您已经为参数包的第一个模板参数和两个元素提供了显式模板参数。但是包中可能还有更多元素。因此函数参数还有一个包含模板参数的类型需要推导(基本上my::test<int(int, int, Ts...)>)。

因此模板参数推导将应用于 argument/parameter 对并且它将失败,因为您提供的函数参数没有 my::test 类型。

template <typename R, typename A, typename B>
void install2(const char name[], my::test<R(A, B)> func)

您已经明确地为所有模板参数提供了模板参数,因此 my::test<R(A, B)> func 将不再是推导上下文。

如问题评论中所述,install2<int, int, int>({add}); 也有效,因为大括号使函数 argument/parameter 对成为 non-deduced 上下文。


如果您希望能够使用显式模板参数且不使用大括号调用函数,您可以使函数参数始终是 non-deduced 上下文,例如使用 C++20 的 std::type_identity :

template <typename R, typename ...Ts>
void install2(std::type_identity_t<my::test<R(Ts...)>> func)

但是,如果没有显式模板参数列表,就不可能再调用它了

您可以同时使用此版本和原始版本作为重载,将一个版本转发到另一个版本,以涵盖您在示例代码中提到的所有情况。