Как можно получить указатель функции на собственный оператор ()

Я хотел бы иметь указатель функции на функцию operator() матрицы Eigen. В частности, матричный класс Operator() Eigen's VectorXi, который принимает один индекс. т.е. оператор, которого я использую, когда звоню:

VectorXi V(1);
...
VectorXi::Index i = 0;
VectorXi::Scalar& vi = V(i); // <-- this one

Что я пробовал:

VectorXi::Scalar& (*value_at_i)(VectorXi::Index i ) = &VectorXi::operator();

Но это дает мне очень длинную ошибку:

...: error: no matches converting function ‘operator()’ to type ‘int& (*)(Eigen::DenseIndex)’
/usr/local/include/eigen3/Eigen/src/Core/DenseCoeffsBase.h:124: error: candidates are: typename Eigen::internal::conditional<(bool)((Eigen::internal::traits<T>::Flags & Eigen::LvalueBit)), const typename Eigen::internal::traits<T>::Scalar&, typename Eigen::internal::conditional<Eigen::internal::is_arithmetic<typename Eigen::internal::traits<T>::Scalar>::value, typename Eigen::internal::traits<T>::Scalar, const typename Eigen::internal::traits<T>::Scalar>::type>::type Eigen::DenseCoeffsBase<Derived, 0>::operator()(typename Eigen::internal::traits<T>::Index, typename Eigen::internal::traits<T>::Index) const [with Derived = Eigen::Matrix<int, -0x00000000000000001, 1, 0, -0x00000000000000001, 1>]
/usr/local/include/eigen3/Eigen/src/Core/DenseCoeffsBase.h:184: error:                 typename Eigen::internal::conditional<(bool)((Eigen::internal::traits<T>::Flags & Eigen::LvalueBit)), const typename Eigen::internal::traits<T>::Scalar&, typename Eigen::internal::conditional<Eigen::internal::is_arithmetic<typename Eigen::internal::traits<T>::Scalar>::value, typename Eigen::internal::traits<T>::Scalar, const typename Eigen::internal::traits<T>::Scalar>::type>::type Eigen::DenseCoeffsBase<Derived, 0>::operator()(typename Eigen::internal::traits<T>::Index) const [with Derived = Eigen::Matrix<int, -0x00000000000000001, 1, 0, -0x00000000000000001, 1>]
/usr/local/include/eigen3/Eigen/src/Core/DenseCoeffsBase.h:405: error:                 typename Eigen::internal::traits<T>::Scalar& Eigen::DenseCoeffsBase<Derived, 1>::operator()(typename Eigen::internal::traits<T>::Index) [with Derived = Eigen::Matrix<int, -0x00000000000000001, 1, 0, -0x00000000000000001, 1>]
/usr/local/include/eigen3/Eigen/src/Core/DenseCoeffsBase.h:347: error:                 typename Eigen::internal::traits<T>::Scalar& Eigen::DenseCoeffsBase<Derived, 1>::operator()(typename Eigen::internal::traits<T>::Index, typename Eigen::internal::traits<T>::Index) [with Derived = Eigen::Matrix<int, -0x00000000000000001, 1, 0, -0x00000000000000001, 1>]

Как правильно получить указатель функции на этот оператор?


person Alec Jacobson    schedule 09.02.2012    source источник
comment
Из любопытства, почему вы пытаетесь это сделать?   -  person cmannett85    schedule 09.02.2012
comment
У меня есть матрица целых чисел T. И вектор карты IM, который принимает значение, которое может встречаться в T, и отображает его в новое значение. Я хотел бы отобразить все значения в T через IM с помощью одной строки. Что-то вроде: T.unaryExpr(ptr_fun(bind1st(mem_fun(get_value,&IM))));   -  person Alec Jacobson    schedule 09.02.2012
comment
Простое решение - это, конечно, тривиальная оболочка VectorXi::Scalar& value_at_i(VectorXi const& v, VectorXi::Index i ) { return v(i); }   -  person MSalters    schedule 10.02.2012


Ответы (3)


Просто чтобы сделать это немного более явным, и потому что мне было любопытно... следуя ответу Расмуса, я попробовал следующий код, и он компилируется и делает то, что вы, кажется, хотите.

VectorXi T(5); T << 2,1,0,2,1; 
VectorXi IM(4); IM << 10,20,30,40; 
// IM maps 0 to 10, 1 to 20, 2 to 30 and 3 to 40

VectorXi::Scalar& (VectorXi::*get_value)(VectorXi::Index) = &VectorXi::operator();
VectorXi res = T.unaryExpr(bind1st(mem_fun(get_value), &IM));
// res is now 30, 20, 10, 30, 20
person Jitse Niesen    schedule 10.02.2012

Вы не можете создать указатель функции на функцию-член. В С++ есть поддержка указателя на функцию-член, но, вероятно, это не то, что вам нужно. Соглашение состоит в том, чтобы передать функтор вместо функции. Функтор — это класс с реализованным оператором (). Это именно то, что у вас есть в вашем классе, поэтому просто передайте исходный класс в качестве функтора.

РЕДАКТИРОВАТЬ: Ниже приведен пример указателя на функции-члены в С++ для оператора () класса T.

void (T::*op)(int) = &T::operator();
T t;
(t.*op)(5);
person rasmus    schedule 09.02.2012
comment
В С++ есть поддержка указателя на функцию-член, но, вероятно, это не то, что вам нужно. Я думаю, это то, что я хочу. Можно ли получить его за вышеперечисленное? - person Alec Jacobson; 09.02.2012
comment
-1. PMF определенно является целью вопроса. Проблема в вопросе заключается в сбое разрешения перегрузки. Это рассматривается в пункте 13.4 стандарта. - person MSalters; 09.02.2012
comment
Я не согласен. Он пытается создать нормальный указатель на функцию из оператора. Проблема, которую он показывает, не связана с перегрузкой. - person rasmus; 09.02.2012
comment
Проблема в том, что он действительно пытается присвоить PMF (&VectorXi::operator()) обычному указателю на функцию. - person MSalters; 10.02.2012

Решение состоит в том, чтобы указать правильную перегрузку. То, что вы видите, это сбой разрешения перегрузки. Есть 4 кандидата, и ни один не соответствует подписи value_at_i.

Вы почти наверняка хотите Eigen::internal::traits<T>::Scalar& Eigen::DenseCoeffsBase<Derived, 1>::operator()(typename Eigen::internal::traits<T>::Index) [with Derived = Eigen::Matrix<int, -0x00000000000000001, 1, 0, -0x00000000000000001, 1>].

Это противная подпись. Тем не менее, обратите внимание, что есть три важные части:

  • Тип возврата Eigen::internal::traits<T>::Scalar&
  • Тип класса Eigen::DenseCoeffsBase<Derived, 1>
  • Тип аргумента Eigen::internal::traits<T>::Index

Соответствующее правило для выбора перегрузки в этом случае весьма специфично: «Выбрана функция, тип которой идентичен типу функции целевого типа, необходимого в контексте». Там нет никакой настройки, и есть даже примечание (13.4/7), показывающее это.

Поэтому мое текущее предположение состоит в том, что проблема заключается в типе класса Eigen::DenseCoeffsBase<Derived, 1>, который не является VectorXi. Два других типа — это определения типов, которые не вводят новые типы.

person MSalters    schedule 09.02.2012
comment
Но как мне преобразовать эту подпись в актерский состав/назначение, как в исходном посте? - person Alec Jacobson; 09.02.2012
comment
Приведение не требуется, просто обычное разрешение перегрузки. Но вам нужно правильно указать тип, чтобы разрешение перегрузки работало. Я не вижу T в выводе компилятора, так что это всего лишь предположение, но я бы сказал VectorXi::Scalar& (VectorXi::*value_at_i)(VectorXi::Index i ) = &VectorXi::operator(); - person MSalters; 10.02.2012