Re: Help with constness and output operator<<
On 23 Sep., 16:23, "marco.guazz...@gmail.com"
<marco.guazz...@gmail.com> wrote:
Suppose you have a class, say "foobar", which let you store elements
in an array of predefined size, such that:
* only elements at even position are assignable [i.e., foo(i) = value
if (i % 2 == 0)]
* elements at odd position are set automatically to zero [i.e., foo(i)
= 0 if (i % 2 == 0)]
To do this I have two methods of foobar:
--- [snip] ---
template <typename T>
class foobar
{
...
reference operator()(std::size_t i)
{
if (!(i % 2))
{
return v_[i];
}
throw std::runtime_error("Not assignable");
}
const_reference operator()(std::size_t i) const
{
if (!(i % 2))
{
return v_[i];
}
return zero_; // The constant 0}
};
--- [/snip] ---
The problem is that the "const" method is not called in the output
operator <<.
In fact when I execute the line:
std::cout << foo(1) << std::endl
Instead of getting zero as output (resulting from the call to the
const method) I get the exception "Not assignable".
To make it to work I have to explicitly cast to type "foobar const&".
Where I am wrong?
It's *not* a compiler problem, but a design problem.
First I wonder your expectations: The example program
creates an object foo of type foobar. This object is not
declared const, so why did you expect that the const
overload is selected at the use-case mentioned above?
Remember that member functions with cv-qualifiers do
participate in overload resolution. So what happens
in your example is somewhat easier to understand,
if you replace the member function call operator by
two free functions:
reference get(foobar&, std::size_t i); // (a)
reference get(const foobar&, std::size_t i); // (b)
So, if you have an non-const lvalue of type
foobar, it will preferably select (a) over (b).
Exactly this is what happens in your example.
You have different options to fix that:
1) Declare the created object as an const
lvalue. In this case (b) is the one and only
one possible overload that could be selected.
2) In your particular example (1) doesn't work,
because you modify the object in the first part
of your function. In this case it would be helpful
to provide a helper function, that does the same
thing as a const_cast which *adds* cv-qualifiers.
A simple overload suffices:
inline const foobar& cget(const foobar& c) { return c; }
HTH & Greetings from Bremen,
Daniel Kr?gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]