C++ 如何将函数名作为编译时参数传递?

C++ 如何将函数名作为编译时参数传递?,c++,templates,metaprogramming,C++,Templates,Metaprogramming,到目前为止,我能够通过名称检测类中是否存在函数,而不需要签名,如下所示: 以下代码深受此问题答案的启发: 我知道应该为不同的修饰符创建不同的专门化,例如const成员函数 template <typename T, typename TReturn, typename... Args> struct function_traits<TReturn( T::* )( Args... )> { using return_type = TReturn; usin

到目前为止,我能够通过名称检测类中是否存在函数,而不需要签名,如下所示:

以下代码深受此问题答案的启发:

我知道应该为不同的修饰符创建不同的专门化,例如const成员函数

template <typename T, typename TReturn, typename... Args>
struct function_traits<TReturn( T::* )( Args... )>
{
    using return_type = TReturn;
    using arguments = std::tuple<Args...>;

    static std::size_t constexpr arg_count = sizeof...( Args );

    template <std::size_t N, typename = void>
    struct argument
    {
        using type = std::tuple_element_t<N, arguments>;
    };

    template <std::size_t N>
    struct argument<N, std::enable_if_t<( !( N < arg_count ) ), void>> {};
};
模板
结构功能特性
{
使用返回类型=t返回;
使用参数=std::tuple;
静态std::size\u t constexpr arg\u count=sizeof…(Args);
模板
结构参数
{
使用type=std::tuple\u元素\u t;
};
模板
结构参数{};
};
<>和我自己的代码作为<强> 22.4.4<强> > <强> C++编程语言,第四版<强>,因为我使用<强VC++2015 >/P>
template <typename T>
struct has_func_f
{
private:
    template <typename C, typename = void>
    struct get_result
    {
        static bool constexpr value = false;
    };

    // need <function_name> as a class parameter so I can append and get &C::<function_name>
    template <typename C>
    struct get_result<C, std::enable_if_t<( std::is_same<decltype( ( decltype( std::declval<typename function_traits<decltype( &C::f )>::arguments>() ) ) ( std::declval<typename function_traits<decltype( &C::f )>::arguments>() ), std::true_type() ), std::true_type>::value ), void>>
    {
        static bool constexpr value = true;
    };

public:
    static bool constexpr value = get_result<T>::value;
};
模板
结构具有\u func\u f
{
私人:
模板
结构获取结果
{
静态布尔constexpr值=false;
};
//需要作为类参数,以便我可以追加并获取&C::
模板
结构获取结果
{
静态布尔constexpr值=真;
};
公众:
静态bool constexpr value=get_result::value;
};
只要名称匹配,该代码就可以检测任何函数签名。我的示例用法:

struct A {};
struct B { float f(int, double); };
struct C { void f(); };

int main()
{
    has_func_f<A>::value; // false
    has_func_f<B>::value; // true
    has_func_f<C>::value; // true

    return 0;
}
struct A{};
结构B{float f(int,double);};
结构C{void f();};
int main()
{
has_func_f::value;//false
has_func_f::value;//true
has_func_f::value;//true
返回0;
}

所以我的问题是,我怎么可能做我想做的事?我看了又看,最近的一件事是使用宏为我想要的函数名生成适当的结构。还有别的办法吗?

我不明白这背后的原因。我让编译器和链接器告诉我是否存在一个方法。你的代码不是有效的C++(它使用MSVC扩展),并且不与重载方法一起工作(至少乍一看)。与大多数问题一样,答案是用宏来破解,最后用一个很差的解决方案,等待C++的反射,或者不使用原始C++类型。最佳答案取决于您的应用程序是什么,但这些类型的问题在100次中有99次是空闲的。此代码背后的原因是,当模板参数没有函数时,试图从另一个模板类调用函数时,避免出现编译时错误。所以说,模板类可以与有f()和没有f()的模板参数一起使用,而不会出现编译错误。我最初的动机实际上是缺乏概念。我可能最终在不知道的情况下使用了MSVC扩展,因为我必须看看VC++是如何为std::is_assignable之类的项目实现这种功能的。它不适用于重载方法,因为我只测试类是否有具有该名称的函数。重载可以由包含函数参数类型的元组模板参数作为目标。使用多态lambda编写一个简短的特殊测试,如下所示:
[](auto&&p)->decltype((void)p.f()){}
您可以类似地检查
[](auto p)->decltype(&unwrap::f){}
,或者通过别名模板
使用has_f=decltype(&T::f)使用Yakk的变体