将模板参数类型转发到 std::function?

问题描述

我正在尝试编写一个通用包装器,用于从 C++ 驱动程序构建 Python 函数。首先,我希望能够使用一些模板魔术来生成关联的 ctypes 并能够打印它们。我有一切工作,但我似乎无法将函数签名类型拉上一层,这违背了目的......

我目前在 godbolt 上对该问题进行了以下最小复制:

#include <functional>
#include <iostream>

template <typename T>
struct ctype
{
    using type = void*;
    static constexpr char name[]  = "c_void_p";
};

template <>
struct ctype<int>
{
    static constexpr char name[]  = "c_int";
};

template <>
struct ctype<double>
{
    static constexpr char name[]  = "c_double";
};

template<typename T> 
struct function_traits;  

template<typename R,typename ...Args> 
struct function_traits<std::function<R(Args...)>>
{
    static constexpr size_t nargs = sizeof...(Args);

    using result_ctype = ctype<R>;

    template <size_t i>
    using arg_ctype = ctype<typename std::tuple_element<i,std::tuple<Args...>>::type>;
};

template <typename FuncSignature>
void log_function_signature()
{
    // using function_proto = function_traits<std::function<double(double,int)>>; // OK
    using function_proto = function_traits<std::function<FuncSignature>>; // BAD? Why?
    std::cout << function_proto::result_ctype::name << std::endl;
    std::cout << function_proto::arg_ctype<0>::name << std::endl;
    std::cout << function_proto::arg_ctype<1>::name << std::endl;
}

double foobar(double x,int y)
{
    return x * y;
}

int main() {
    log_function_signature<double(double,int)>();
}

function_traits 改编自此答案:https://stackoverflow.com/a/9065203/2242096。理想情况下,我会直接在 FuncSignature 内使用 log_function_signature,但我无法弄清楚为什么这是不允许的。编译器给了我以下内容

<source>: In function 'void log_function_signature()':
<source>:42:48: error: '::name' has not been declared; did you mean 'rename'?
   42 |     std::cout << function_proto::arg_ctype<0>::name << std::endl;
      |                                                ^~~~
      |                                                rename
<source>:43:48: error: '::name' has not been declared; did you mean 'rename'?
   43 |     std::cout << function_proto::arg_ctype<1>::name << std::endl;
      |                                                ^~~~
      |                                                rename
<source>: In instantiation of 'void log_function_signature() [with FuncSignature = double(double,int)]':
<source>:52:48:   required from here
<source>:42:34: error: dependent-name 'function_proto::arg_ctype' is parsed as a non-type,but instantiation yields a type
   42 |     std::cout << function_proto::arg_ctype<0>::name << std::endl;
      |                                  ^~~~~~~~~
<source>:42:34: note: say 'typename function_proto::arg_ctype' if a type is meant
<source>:43:34: error: dependent-name 'function_proto::arg_ctype' is parsed as a non-type,but instantiation yields a type
   43 |     std::cout << function_proto::arg_ctype<1>::name << std::endl;
      |                                  ^~~~~~~~~
<source>:43:34: note: say 'typename function_proto::arg_ctype' if a type is meant
ASM generation compiler returned: 1
<source>: In function 'void log_function_signature()':
<source>:42:48: error: '::name' has not been declared; did you mean 'rename'?
   42 |     std::cout << function_proto::arg_ctype<0>::name << std::endl;
      |                                                ^~~~
      |                                                rename
<source>:43:48: error: '::name' has not been declared; did you mean 'rename'?
   43 |     std::cout << function_proto::arg_ctype<1>::name << std::endl;
      |                                                ^~~~
      |                                                rename
<source>: In instantiation of 'void log_function_signature() [with FuncSignature = double(double,but instantiation yields a type
   43 |     std::cout << function_proto::arg_ctype<1>::name << std::endl;
      |                                  ^~~~~~~~~
<source>:43:34: note: say 'typename function_proto::arg_ctype' if a type is meant
Execution build compiler returned: 1

为什么模板类型在函数内部编写时有效,而通过模板传入时无效?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)