шаблоны — Как правильно определить функциональные объекты в C ++?

Я получаю очень странную ошибку в очень простом коде, который не могу исправить.

Я определил следующий функциональный объект:

template<const size_t n> class L2Norm {
public:
double operator()(const Point<n>& p) {
/* computes the L2-norm of the point P ... */

}
double operator()(const Point<n>& p,
const Point<n>& q) {
return L2Norm<n>(p-q);
}
};

Здесь класс Point<n> хорошо определено, прежде чем хранить n координаты точки в nпространство (с необходимыми операторами, …).

Я ожидаю получить l2-норму точки p (создан как Point<5> p например) используя L2Norm<5>(p), Но это дает мне следующую ошибку:

no matching function for call to ‘L2Norm<5ul>::L2Norm(Point<5ul>&)’
note: candidates are: L2Norm<n>::L2Norm() [with long unsigned int n = 5ul]
note:   candidate expects 0 arguments, 1 provided
note: L2Norm<5ul>::L2Norm(const L2Norm<5ul>&)
note:   no known conversion for argument 1 from ‘Point<5ul>’ to ‘const L2Norm<5ul>&’

Я почти уверен, что делаю очень глупую ошибку, но не могу узнать где!


Постскриптум Как побочный вопрос, было бы намного лучше, если бы я мог сказать L2Norm(p) только и компилятор обнаруживает параметр шаблона из p но, насколько мне известно, это невозможно. Я прав?

4

Решение

Вам нужно создать экземпляр и вызвать его оператор (), В настоящее время вы пытаетесь вызвать несуществующий конвертирующий конструктор.

return L2Norm<n>()(p-q); // C++03 and C++11
//              ^^

или же

return L2Norm<n>{}(p-q);  // c++11
//              ^^

Кроме того, вы можете сделать ваши операторы вызова const также, поскольку маловероятно, что вызовы к ним должны привести к изменению наблюдаемого состояния экземпляра:

template<const size_t n> class L2Norm
{
public:
double operator()(const Point<n>& p) const { .... }
double operator()(const Point<n>& p, const Point<n>& q) const { .... }
};
7

Другие решения

Как уже ответил @ juanchopanza, вы должны сначала создать объект:

L2Norm<5>()(p-q);

Теперь вы можете даже получить:

L2Norm()(p-q)

используя так называемый «объект полиморфной функции». Делая простой тип класса с шаблоном operator() вместо:

class L2Norm {
public:
template<const size_t n>
double operator()(const Point<n>& p) const {
/* computes the L2-norm of the point P ... */
}
template<const size_t n>
double operator()(const Point<n>& p,
const Point<n>& q) const {
return operator()(p-q);
}
};

Недостатком является то, что вы не можете сделать это адаптируемой двоичной функцией для C ++ 03, поэтому она не будет работать в некоторых алгоритмах C ++ 03. В boost это будет, если вы предоставите соответствующие определения, а в C ++ 11 это должно быть обработано благодаря использованию decltype,

С этой техникой вы Можно устранить лишнее () :

class {
public:
template<const size_t n>
double operator()(const Point<n>& p) const {
/* computes the L2-norm of the point P ... */
}
template<const size_t n>
double operator()(const Point<n>& p,
const Point<n>& q) const {
return operator()(p-q);
}
} L2Norm;

L2norm(p-q); // Uses the object L2Norm, which has an unnamed type.
2

По вопросам рекламы [email protected]