Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/164.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 获取模板可调用对象的参数类型_C++_Templates_C++11_Template Meta Programming - Fatal编程技术网

C++ 获取模板可调用对象的参数类型

C++ 获取模板可调用对象的参数类型,c++,templates,c++11,template-meta-programming,C++,Templates,C++11,Template Meta Programming,考虑以下功能: template<class F> void register_handler( F& f ) // any callable object { // find out T - the argument type of f } 但这似乎有些过分,因为typeF应该已经包含了关于typeT的必要信息,如果F是std::function您应该能够使用its成员类型并使用“std::is_same”进行检查: template<class F>

考虑以下功能:

template<class F>
void register_handler( F& f ) // any callable object
{
   // find out T - the argument type of f
}

但这似乎有些过分,因为type
F
应该已经包含了关于type
T
的必要信息,如果F是
std::function
您应该能够使用its
成员类型
并使用“std::is_same”进行检查:

template<class F>
void register_handler( F& f ) // any callable object
{
   // find out T - the argument type of f
   if(std::is_same<int, F::argument_type>::value)
   { .... }
   //etc .....

}
模板
void register\u handler(F&F)//任何可调用对象
{
//找出T—f的参数类型
if(std::is_same::value)
{ .... }
//等等。。。。。
}
一个运行良好的例子


但是这种代码很快就会变得一团糟,难以维护。

假设
F
是任何可调用类型,则无法获取其参数类型。考虑这一点:

struct callable
{
    void operator() (int);
    void operator() (float *);
    void operator() (std::string const &);
    void operator() (std::list<int> &);
};
struct可调用
{
void操作符()(int);
void操作符()(float*);
void运算符()(std::string const&);
void操作符()(std::list&);
};

这里的参数类型是不明确的。

您可以使用sfinae并测试您的参数是否可转换为具有所需参数的std::函数:

#include <type_traits>
#include <functional>
#include <iostream>

class A
{
};

template <class T>
struct Functor
{
  void operator()(const T& t)
  {}
};

struct Register
{
  //int parameters
  template <class T>
  static void RegisterFunctor(const T& /*functor*/, typename std::enable_if<std::is_constructible<typename std::function<void (int)>, T>::value >::type* = 0)
  {
    std::cout << "Register int func" << std::endl;
  }

  //A parameters
  template <class T>
  static void RegisterFunctor(const T& /*functor*/, typename std::enable_if<std::is_constructible<typename std::function<void (A)>, T>::value >::type* = 0)
  {
    std::cout << "Register a func" << std::endl;
  }
};

void intFunc(int) {}
void aFunc(A){}

int main(int /*argc*/, char */*argv*/[])
{
  Functor<int> intFunctor;
  Functor<A> aFunctor;

  Register::RegisterFunctor(intFunctor);
  Register::RegisterFunctor(&intFunc);
  Register::RegisterFunctor(aFunctor);
  Register::RegisterFunctor(&aFunc);
  return 0;
}
#包括
#包括
#包括
甲级
{
};
模板
结构函子
{
void运算符()(常量T&T)
{}
};
结构寄存器
{
//int参数
模板
静态无效注册表函数(常量T&/*函数*/,类型名std::enable_if::type*=0)
{
std::cout这展示了如何实现一些函数类型特征。这些特征应该适用于所有可调用的对象(异常:多态函子:p)。您可以迭代这些参数,并使用它们的类型执行一些sfinae或作为附加模板参数

复制自的功能特征:

#包括
//如图所示http://functionalcpp.wordpress.com/2013/08/05/function-traits/
模板
结构功能特征;
//函数指针
模板
结构功能特征:公共功能特征
{};
模板
结构功能特性
{
使用返回类型=R;
静态constexpr std::size\t arity=sizeof…(Args);
模板
结构参数
{
静态_断言(N
测试代码:

#include <iostream>

class A
{
};

template <class T>
struct Functor
{
  void operator()(const T& t)
  {}
};

struct Register
{
  //int parameters
  template <class T>
  static void RegisterFunctor(const T& /*functor*/, typename std::enable_if<std::is_same<typename function_traits<T>::template argument<0>::type, const int&>::value>::type* = 0)
  {
    std::cout << "Register int func" << std::endl;
  }

  //A parameters
  template <class T>
  static void RegisterFunctor(const T& /*functor*/, typename std::enable_if<std::is_same<typename function_traits<T>::template argument<0>::type, const A&>::value>::type* = 0)
  {
    std::cout << "Register int func" << std::endl;
  }
};

void intFunc(const int&) {}
void aFunc(const A&){}

int main(int /*argc*/, char */*argv*/[])
{
  Functor<int> intFunctor;
  Functor<A> aFunctor;

  Register::RegisterFunctor(intFunctor);
  Register::RegisterFunctor(&intFunc);
  Register::RegisterFunctor(aFunctor);
  Register::RegisterFunctor(&aFunc);
  return 0;
}
#包括
甲级
{
};
模板
结构函子
{
void运算符()(常量T&T)
{}
};
结构寄存器
{
//int参数
模板
静态无效注册表函数(常量T&/*函数*/,类型名std::enable_if::type*=0)
{

std::在c++1y中,如果使用泛型lambda
[](auto v){}
@lisyarus,则可以将其定义为默认值。在使用sfinae时,如果发现多种可能性,这将是首选的重载。@galop1n:泛型lambda只是
模板运算符()的一种糖类
,因此c++11和c++03中也存在同样的问题。@davidfurle:要选择默认重载,我应该获得可能的重载列表,这是不可能的。如果要事先定义可能的签名,只需测试该类型是否可以用这些签名调用,而忽略“获取参数类型”胡说八道。这是不必要的限制,在一般情况下不起作用;在Boost或标准库中采用多态lambda和多态可调用对象时,这些限制尤其有问题。@R.MartinhoFernandes这是正确的。此解决方案不处理多态lambda。在sfinae的特殊情况下,它可能是错误的e因为你可以测试lambda是否支持使用某一类型的参数调用being->请参阅我的其他答案我认为一般的问题是我们不知道类型参数的用途是什么。如果它用于执行sfinae,则可以测试functor是否支持调用being。如果它用于其他目的,则无法工作th多态函子。但是用例可能只支持非多态函子。您可以专门化模板以满足您的需要。我记不起确切的语法和确切的实践,但您可以查看:希望这有帮助:)编辑:我找到了更好的链接您使用这些信息的目的是什么?如下所述,您的问题可以一般来说,无法解决,但引发问题的问题可能是可以解决的。请描述您的问题,而不是您的解决方案。“获取参数类型
f
!”是您当前遇到的问题的解决方案吗?如果有帮助,“因为类型f应该已经包含关于类型T的必要信息。”是一个无效的假设。在RapidCheck中可以找到一个很好的参考实现,特别是请注意,此实现只能处理已实现的参数类型(大多数基本类型都已实现)。请注意,
argument\u type
在C++17中被弃用,在C++20中被删除:
#include <tuple>

// as seen on http://functionalcpp.wordpress.com/2013/08/05/function-traits/
template<class F>
struct function_traits;

// function pointer
template<class R, class... Args>
struct function_traits<R(*)(Args...)> : public function_traits<R(Args...)>
{};

template<class R, class... Args>
struct function_traits<R(Args...)>
{
    using return_type = R;

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

    template <std::size_t N>
    struct argument
    {
        static_assert(N < arity, "error: invalid parameter index.");
        using type = typename std::tuple_element<N,std::tuple<Args...>>::type;
    };
};

// member function pointer
template<class C, class R, class... Args>
struct function_traits<R(C::*)(Args...)> : public function_traits<R(C&,Args...)>
{};

// const member function pointer
template<class C, class R, class... Args>
struct function_traits<R(C::*)(Args...) const> : public function_traits<R(C&,Args...)>
{};

// member object pointer
template<class C, class R>
struct function_traits<R(C::*)> : public function_traits<R(C&)>
{};

// functor
template<class F>
struct function_traits
{
    private:
        using call_type = function_traits<decltype(&F::operator())>;
    public:
        using return_type = typename call_type::return_type;

        static constexpr std::size_t arity = call_type::arity - 1;

        template <std::size_t N>
        struct argument
        {
            static_assert(N < arity, "error: invalid parameter index.");
            using type = typename call_type::template argument<N+1>::type;
        };
};

template<class F>
struct function_traits<F&> : public function_traits<F>
{};

template<class F>
struct function_traits<F&&> : public function_traits<F>
{};
#include <iostream>

class A
{
};

template <class T>
struct Functor
{
  void operator()(const T& t)
  {}
};

struct Register
{
  //int parameters
  template <class T>
  static void RegisterFunctor(const T& /*functor*/, typename std::enable_if<std::is_same<typename function_traits<T>::template argument<0>::type, const int&>::value>::type* = 0)
  {
    std::cout << "Register int func" << std::endl;
  }

  //A parameters
  template <class T>
  static void RegisterFunctor(const T& /*functor*/, typename std::enable_if<std::is_same<typename function_traits<T>::template argument<0>::type, const A&>::value>::type* = 0)
  {
    std::cout << "Register int func" << std::endl;
  }
};

void intFunc(const int&) {}
void aFunc(const A&){}

int main(int /*argc*/, char */*argv*/[])
{
  Functor<int> intFunctor;
  Functor<A> aFunctor;

  Register::RegisterFunctor(intFunctor);
  Register::RegisterFunctor(&intFunc);
  Register::RegisterFunctor(aFunctor);
  Register::RegisterFunctor(&aFunc);
  return 0;
}