Anton
Anton

Reputation: 45

Cannot overload functions distinguished by return type alone

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

Answers (2)

Cheers and hth. - Alf
Cheers and hth. - Alf

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

Luchian Grigore
Luchian Grigore

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

Related Questions