mapbox / variant

C++11/C++14 Variant
BSD 3-Clause "New" or "Revised" License
371 stars 100 forks source link

Bug leads to crash program when using .set<T>() and then apply_visitor() #152

Open huanncbg opened 7 years ago

huanncbg commented 7 years ago

include

include <mapbox/variant.hpp>

include

using namespace std; using namespace mapbox::util;

// Forward declaration struct HPArray; struct HPTable; using HPVariant = variant<string,float,recursive_wrapper>;

struct HPArray{ template <typename ...Args> HPArray(Args ...args){ values.emplace(std::forward(args)...); } unordered_map<int,HPVariant> values; };

struct Visitor{

void operator()(const string &str){
    cout << str <<endl;;
}

void operator()(const float &value){
    cout << value <<endl;
}

void operator()(HPArray array){
    for (size_t i = 0; i < array.values.size(); i++)
    {
        apply_visitor(*this,array.values[i]);
    }
}

};

int main() { HPArray ar; ar.values[0] = HPVariant("String"); ar.values[1] = 2.0f;

HPVariant var;
var.set<HPArray>(ar);
Visitor visitor;
apply_visitor(visitor,var);
return 0;

}

ricardocosme commented 7 years ago

As far as I see, it seems to me that there is a precondition to variant::set<T>(). T shall be in variant::Types.... Take a look at mapbox/variant.hpp:{704, 705}.

You should use T equals mapbox::util::recursive_wrapper<HPArray> instead of HPArray.

Demo:

struct HPArray;
using HPVariant = mapbox::util::variant<
    std::string,
    float,
    mapbox::util::recursive_wrapper<HPArray>
>;
struct HPArray { /*...*/ };

int main()
{
    HPVariant var;
    //It should be: var.set<mapbox::util::recursive_wrapper<HPArray>>(...)
    var.set<HPArray>(HPArray{}); 
    mapbox::util::apply_visitor([](auto&& o){ /*...*/ }, var);
}

BTW, is there a reason to maintain variant::set<T>() to 2.0.0?