从实际参数捕获函数参数类型

是否有可能捕获正式参数的类型,只有函数名称和实际参数?

我需要类似于decltype的东西,但它应该返回函数类型而不是函数的返回类型。

我用C ++ 11找到了一个半解决方案。 如果该函数未被重载,则可以使用decltype来获取签名,仅指定函数名称和模板参数(如果有),但不指定实际参数:

template<class F>
struct my_function_traits;

// function pointer
template<class R, class Arg>
struct my_function_traits<R(*)(Arg)> : public my_function_traits<R(Arg)>
{
  typedef Arg type;
};

template<class R, class Arg1>
struct my_function_traits<R(Arg1)>
{
  typedef Arg1 type;
};

namespace itk
{
template <typename PixelType, unsigned Dimension>
class Image;
}

template <typename TPixel, unsigned VDimension>               
void func2(itk::Image<TPixel, VDimension>* image) {}


int main()
{
  typedef my_function_traits< decltype(func2<int, 2>) > Traits;

  Traits::type var = 0;

  return 0;
}

这很好,但如果我添加这个其他函数,decltype将无法解析类型:

template <typename TPixel, unsigned VDimension>               
void func2(const itk::Image<TPixel, VDimension>* image, int i) {}

有道理,因为函数名称不明确,两个版本都有相同的模板参数。 但编译器必须能够从实际参数的静态类型中找出正确的函数。 问题是,只要我指定它们,decltype就返回表达式的类型,即函数的返回类型。

  itk::Image<int, 3>* image;
  int a = 3;
  ...
  typedef my_function_traits< decltype(func2<int, 2>(image, 3)) > Traits;

我的主要目标是检查第一个参数的常量。

谢谢你的帮助!


假设你不知道第一个指针的常量,并且你知道连续的参数类型,你可以使用下面的代码:

template <typename T, typename ...Ts>
struct is_first_arg_const_ptr
{
    template <typename Ret>
    static std::false_type
    is_const(Ret (&f)(T*, Ts...));

    template <typename Ret>
    static std::true_type
    is_const(Ret (&f)(const T*, Ts...));

    // And for methods
    template <typename Ret, typename C>
    static std::false_type
    is_const (Ret (C::*) (T*, Ts...)) /* const volatile & && */;

    template <typename Ret, typename C>
    static std::true_type
    is_const (Ret (C::*) (const T*, Ts...)) /* const volatile & && */;

    // .. complete for all combinations of cv_qualifier and ref
};

现在,正确选择过载是没有歧义的。

现场示例。

对于宏而言,你可以做如下的事情:

template <typename T, typename ...Ts>
constexpr
auto make_is_first_arg_const_ptr(T&& t, Ts&&...)
-> is_first_arg_const_ptr<
    typename std::decay<decltype(*t)>::type,
    typename std::decay<Ts>::type...
>;

#define IS_FIRST_ARG_CONST_PTR(Name, ...) 
    (decltype(make_is_first_arg_const_ptr(__VA_ARGS__).is_const(Name))::value)

然后用它作为

static_assert(!IS_FIRST_ARG_CONST_PTR(func2, image), "");
static_assert(IS_FIRST_ARG_CONST_PTR(func2, image, a), "");
static_assert(IS_FIRST_ARG_CONST_PTR(&MyClass::func2, image, a), "");

请注意,这个宏不适用于func一些原型,因为我从参数中推导出了类型,但在这种情况下你会得到一个编译错误(你可以通过一个更合适的特性来改变std::decay以符合你的需要)。


Boost做到这一点。 看看boost的function_traits:

http://www.boost.org/doc/libs/1_55_0/boost/type_traits/function_traits.hpp

http://www.boost.org/doc/libs/1_55_0/libs/type_traits/doc/html/boost_typetraits/reference/function_traits.html

链接地址: http://www.djcxy.com/p/66505.html

上一篇: Capture function argument type from actual arguments

下一篇: Using auto and decltype to return reference from function in templated class