从trait中获取const或非const引用类型

时间:2010-04-13 10:19:14

标签: c++ templates reference functor traits

我正在编写一个函子F,它接受void(* func)(T)和func的参数arg的函数。

template<typename T>
  void F(void (*func)(T), WhatTypeHere? arg)
{
  func(arg);
}

然后,仿函数F用arg调用func。我希望F不要复制arg,只是为了传递它作为参考。但后来我不能简单地写“void F(void(* func)(T),T&amp;)”因为T可能是一个参考。所以我试着写一个特性,它允许获得适当的T:

参考类型
T -> T&
T& -> T&
const T -> const T&
const T& -> const T&

我想出了类似的东西:

template<typename T>
 struct type_op
{
 typedef T& valid_ref_type;
};

template<typename T>
 struct type_op<T&>
{
 typedef typename type_op<T>::valid_ref_type valid_ref_type;
};

template<typename T>
 struct type_op<const T>
{
 typedef const T& valid_ref_type;
};

template<typename T>
 struct type_op<const T&>
{
 typedef const T& valid_ref_type;
};


template<typename T>
  void F(void (*func)(T), typename type_op<T>::valid_ref_type arg)
{
  func(arg);
}

例如

不起作用
void a(int x) { std::cout << x << std::endl; }
F(&a, 7);

给出错误:     在传递'void F(void(*)(T),typename type_op :: valid_ref_type)的参数2中,从'int'类型的临时类型'int&amp;'类型的非const引用无效初始化[with T = int] “

如何让这个特性发挥作用?

4 个答案:

答案 0 :(得分:5)

template<class T>
struct forwarding { typedef T const& type; };
template<class T>
struct forwarding<T&> { typedef T& type; };

template<typename T>
void F(void (*func)(T), typename forwarding<T>::type arg) {
  func(arg);
}

void a(int x) { std::cout << x << std::endl; }
int main() {
  F(&a, 7);
}

您的映射很接近,您实际上希望T映射到T const&amp;太:

T        -> T const&
T&       -> T&
T const& -> T const&

请注意,参数类型为T const的函数的签名为T! const是一个实现细节:

void f(int const);
typedef void F(int); // typedef of function type
F* p = &f; // no error! f's signature doesn't include const

答案 1 :(得分:2)

您只需删除引用:

template<typename T> struct remove_reference { typedef T type; };
template<typename T> struct remove_reference<T&> { typedef T type; };

然后按如下方式再次添加:

remove_reference<T>::type&

您的功能应声明如下:

template<typename T>
void F( void (*func)(T), const typename remove_reference<T>::type& arg )
{
  func(arg);
}

答案 2 :(得分:1)

我的想法有点模糊,但我认为提升(可能是boost :: bind)只通过提供const T&特征来解决这个问题,并且要求使用ref(x)表示非const参考。

答案 3 :(得分:1)

您还可以使用Boost.TypeTraits中的add_reference来实现所需的类型映射。