I am getting a very strange error on a very simple code that I couldn't fix.
I have defined the following function object:
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);
}
};
Here the class Point<n>
is well defined before to store the n
coordinates of a point in n
-dimensional space (with required operators, ...).
I expect to get the l2-norm of a point p
(created as Point<5> p
for example) using L2Norm<5>(p)
. But this gives me the following error:
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>&’
I'm pretty sure that I am doing a very stupid mistake but I cannot find out where!
P.S. As a side question, it would be much nicer if I could say L2Norm(p)
only and the compiler detects the template parameter from p
but to the best of my knowledge this is not possible. Am I right?
You need to create an instance and call its operator ()
. Currently you are trying to call a non-existent converting constructor.
return L2Norm<n>()(p-q); // C++03 and C++11
// ^^
or
return L2Norm<n>{}(p-q); // c++11
// ^^
As an aside, you might want to make your call operators const
too, since it is unlikely calls to them should result in a change to the observable state of an instance:
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 { .... }
};
As @juanchopanza's already answered, you have to create the object first:
L2Norm<5>()(p-q);
Now, you can even get:
L2Norm()(p-q)
using so called "polymorphic function object". By making a simple class type with template operator()
instead:
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);
}
};
The disadvantage is that you can't make this an adaptable binary function for C++03, so it will not work in some C++03 algorithms. In boost it will if you provide appropriate definitions and in C++11 it should be handled thanks to use of decltype
.
With this technique, you can eliminate the redundant ()
:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With