C++ 以函数为参数提取模板函数中输入参数的类型

C++ 以函数为参数提取模板函数中输入参数的类型,c++,function,templates,signature,C++,Function,Templates,Signature,我有这个功能: template<typename T, int (*F)(T&)> void DoStuff(T& s) { auto an = make_any<T>(s); cout << _GetDataFromAny<MyStruct, F>(an); } 模板 空隙度凝灰岩(T&s) { auto an=使任何(s); cout您可以编写一个助手来推断返回int的函数指针的参数类型: template&

我有这个功能:

template<typename T, int (*F)(T&)>
void DoStuff(T& s)
{
    auto an = make_any<T>(s);
    cout << _GetDataFromAny<MyStruct, F>(an);
}
模板
空隙度凝灰岩(T&s)
{
auto an=使任何(s);

cout您可以编写一个助手来推断返回
int
的函数指针的参数类型:

template<typename T>
T arg_type(int(*)(T&));
模板
T arg_类型(int(*)(T&));
然后稍微重写函数模板,将函数指针作为非类型模板参数,并从中找出参数类型

template<auto F, typename T = decltype(arg_type(F))>
void DoStuff(T& s) {
 // ...
}
模板
空隙度凝灰岩(T&s){
// ...
}

免责声明:这个答案经过了一系列的编辑和更正,非常感谢Jarod42的耐心和帮助,感谢cigien的富有成效的讨论。它比必要的时间长了一点,但我觉得值得保留一点历史。它是:最简单的/我更喜欢的一个/对以前的混乱的一些解释要快速回答,请阅读第二部分


简单的

您可以使用
auto
模板参数(自C++17以来)作为函数指针,并从参数中推断
T

template<auto F, typename T>
void DoStuff(T& s)
{
    int x = F(s);
}

int foo(double&){ return 42;}

int main() {
    double x;
    DoStuff<&foo>(x);
}
现在,以前只会发生在模板(1)内部的错误已经发生在
main
(2)中,并且错误消息更清晰


“错误”

主要是好奇心,考虑从函数指针推导参数类型的方法:

template <typename T> struct param_type;

template <typename R,typename P>
struct param_type< R(*)(P&)> {
    using type = P;
};
    
template<auto F, typename T = typename param_type<decltype(F)>::type>
void DoStuffX(T& s)
{
}

int foo(double&){ return 42;}    

int main() {
    double x;
    DoStuffX<foo>(x);
}
原因是当可以从传递的参数中删除
T
时,不使用默认模板参数(请参阅)。即,
DoStuffX(x);
实际实例化
DoStuffX
。我们仍然可以通过以下方式获得默认模板参数:

int main() {
    std::string x;
    auto f_ptr = &DoStuffX<foo>;
    f_ptr(x);  // error
}
intmain(){
std::字符串x;
自动f_ptr=&DoStuffX;
f_ptr(x);//错误
}

现在用
std::string
调用
DoStuffX
是一个编译器错误,因为这里
DoStuffX
被实例化为
DoStuffX
,使用默认参数(当
DoStuffX
被实例化时,没有参数可用于推断
T
).

我养成了只在写完后重新加载的习惯,更容易看出另一个答案比我的好,而不是试图竞争:嗯,这太快了!我还不能接受答案(所以不让我接受)@magnize_prime_是_463035818是的,我知道你的意思。但是,它并没有真正的竞争;你的解决方案同样有效,发布它也可以。当然,竞争不是,我是在开玩笑。我只是不知道我的会添加什么。我可以尝试在不使用
auto
参数的情况下获取它,但现在已经很晚了请注意
=decltype(arg_type(F))
很少有用,因为
T
是推导出来的。(对
auto-func=&DoStuff;
有用)
模板void-DoStuffY(typename-param_-type::type&s)
是一种替代方法。完全没有推导。函数指针或常规调用是可能的(仅对预期类型)@Jarod42这应该是答案。一定是关于这个问题,不知怎的,我忘记了我知道的一切和更多。我会编辑的
int main() {
    std::string x;
    DoStuffX<foo>(x);
}
int main() {
    std::string x;
    auto f_ptr = &DoStuffX<foo>;
    f_ptr(x);  // error
}