1

I am having trouble maintaining const correctness after trying to retrieve a boost::any instance through boost::any_cast reference casting.

My code:

MyMap paramMapToSet;
MyMap& paramMap = &paramMapToSet;
const MyMap& constParamMap = &paramMapToSet;

A hoe;
paramMap.set(hoe, "structA");

// this works
A& hoeRef = paramMap.getByRef<A>("structA");
hoeRef.myInt = 101;
cout << paramMap.get<A>("structA").myInt << endl; // prints 101

// as well as this:
hoe = constParamMap.get<A>("structA");
cout << hoe.myInt << endl;

// and this:
const A& constHoeRef = paramMap.getByRef<A>("structA");
cout << constHoeRef.myInt << endl;

// however this doesn't work, why?? (error message below)
const A& constHoeRef = constParamMap.getByRef<A>("structA");
cout << constHoeRef.myInt << endl;

I am also a bit confused regarding how come only the last version generates error. The error message I'm getting is this:

C:...\boost_1_58_0\boost\any.hpp:284: error: C2440: 'return' : cannot convert from 'const nonref' to 'A &' Conversion loses qualifiers

Where line 284 looks like this:

return any_cast<const nonref &>(const_cast<any &>(operand));

It is called from a line below:

The implementation:

// a testing class:
struct A{
    int myInt;
    A() = default;
    A(const A& other) : myInt(other.myInt)
        { cout << "Class A is being copied" << endl; }
};

// any-map implementation
class MyMap{
public:
    template<typename T>
    T get(const std::string& path) const
    {
        return any_cast<T>(data.at(path));
    }

    template<typename T>
    const T& getByRef(const std::string& path) const
    {
        return any_cast<T&>(data.at(path)); // compiler originates the error from here
    }

    template<typename T>
    T& getByRef(const std::string& path)
    {
        return any_cast<T&>(data.at(path)); 
    }

    template<typename T>
    void set(T val, const std::string& path)
    {
        data[path] = val;
    }

private:
    std::map<std::string, boost::any> data;
};

You may be thinking MyMap provides useless wrapping functionality that is already there out of the box, however the real implementation has get/set methods that automatically create nested maps inside the internal std::map, providing a cool flexible DOM like data structure.

MatrixAndrew
  • 265
  • 3
  • 13
  • 1
    why dont you make the question look simpler by writing less codes. write only those codes which create doubt in your mind & pit the rest as "// do stuff.." or similar ways. – Ankit Acharya Oct 12 '15 at 15:27
  • 1
    @AnkitAcharya: Because that's the polar opposite of what we ask question authors to do? http://stackoverflow.com/help/mcve `// do stuff` is pointless, unhelpful and annoying. – Lightness Races in Orbit Oct 12 '15 at 15:29
  • 1
    @LightnessRacesinOrbit i understand your point but things as simple as the above can be expressed in simple codes too. thta means better put a small test code rather than a huge PROJECT CODE – DevInd Oct 12 '15 at 15:38
  • 1
    This is really tiny code, what I could have omitted is like one function, namely set(). I thought this is going to be a somewhat more compound problem, in requirement of this context. – MatrixAndrew Oct 12 '15 at 15:41
  • 1
    @CppNITR: Yes, simple is good, but it **must** be _complete_. There is no point in a piece of code with "more stuff here" and "..." scattered throughout it. Consider reading the page I linked you to. – Lightness Races in Orbit Oct 12 '15 at 15:41

1 Answers1

5

I'm just guessing but, surely…

return any_cast<const T&>(data.at(path));
//              ^^^^^^

…no?

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055