Reputation: 45
I am reading "Effective C++" and trying to compile this example from rule 3:
class TextBlock
{
public:
const char& operator[](size_t position) const
{
return text[position];
}
char& operator[](size_t position) const
{
return const_cast<char&>(
static_cast<const TextBlock&>(*this)
[position]
);
}
private:
string text;
};
This must describe how to prevent code duplication; to not write the same code to return a non-const result. I am using VS2012. However I am getting an error. I heard heard that overloaded functions cannot have different return types, but after seeing this I don't know what to think.
Upvotes: 3
Views: 7688
Reputation: 145429
As noted already by others, the problem is that you inadvertently added a const
.
However, more important is that the example you give, from “Effective C++” teaches Bad Things™.
The problem that it deals with is not a problem, and the solution, expressing a non-const
method in terms of a const
method, via casts, is an abomination.
At the same time the real problems (such as ease of debugging, checking argument values, definitions before use for readability) are not dealt with.
Here's better and shorter code:
using Index = ptrdiff_t;
class TextBlock
{
private:
std::string text;
public:
auto operator[]( Index const i ) const
-> char const&
{ return text[i]; }
auto operator[]( Index const i )
-> char&
{ return text[i]; }
};
For the case where you don't have a convenient already-const
-paired underlying representation you can use this support machinery:
template< class A, class B >
struct With_const_as_T_ { using T = typename std::remove_const<B>::type; };
template< class A, class B >
struct With_const_as_T_< A const, B > { using T = B const; };
template< class A, class B >
using With_const_as_ = typename With_const_as_T_<A, B>::T;
… to express both non-const
and const
in terms of a template function, like this:
class TextBlock
{
private:
std::string text;
template< class Self >
static auto at( Self& self, Index const i )
-> With_const_as_<Self, char>&
{ return self.text[i]; }
public:
auto operator[]( Index const i ) const
-> char const&
{ return at( *this, i ); }
auto operator[]( Index const i )
-> char&
{ return at( *this, i ); } // Look, no casts!
};
Upvotes: 3
Reputation: 258648
I think the book says
const char& operator[](size_t position) const
char& operator[](size_t position)
not
const char& operator[](size_t position) const
char& operator[](size_t position) const <--- extra const here
cv-qualifiers are part of a function's signature, return types are not.
Upvotes: 6