3

我正在编写一个仿函数 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&)”,因为 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) [with T =整数]'</p>

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

4

4 回答 4

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& :

T -> T 常量&
T& -> T&
T 常量& -> T 常量&

请注意,参数类型为 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
于 2010-04-13T10:32:58.963 回答
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);
}
于 2010-04-13T10:26:26.960 回答
1

在我看来这有点模糊,但我认为 boost(也许 boost::bind)通过仅提供const T&特征并要求使用ref(x)来表示非常量引用来解决这个问题。

于 2010-04-13T10:28:13.773 回答
1

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

于 2010-04-13T11:59:27.860 回答