mpark / variant

C++17 `std::variant` for C++11/14/17
https://mpark.github.io/variant
Boost Software License 1.0
659 stars 88 forks source link

store size_t in a variant ? #40

Closed SuperFola closed 5 years ago

SuperFola commented 6 years ago

Hi,

I am trying to store size_t as well as int64_t, double, bool, string in a variant. Storing the 4 last types work fine, but I get a bad_variant_access when trying to get/set the size_t with this code :

#include <iostream>
#include <cstdint>
#define MPARK_EXCEPTIONS
#include <mpark/variant.hpp>

using namespace std;  // i know it's bad, it's just for testing

int main()
{
    mpark::variant<int64_t, double, bool, string, size_t> v;
    mpakr::get<size_t>(v) = 15;  // right there
    return 0;
}

edit : updating code to fix compile errors

SaadAttieh commented 6 years ago

There are some compile errors in your code. After making changes such that it compiles, your issue becomes clear. Here is some working code with a comment that should show your problem.

include

include

define MPARK_EXCEPTIONS

include "mpark/variant.hpp"

using namespace std; // i know it's bad, it's just for testing

int main() { mpark::variant<int64_t, double, bool, string, size_t> v; // v is not assigned to size_t here, so you cannot call mpark::get v.emplace(0); //now it is correctly assigned to type size_t mpark::get(v) = 15; return 0; }

If the type of x, where x is the value you are assigning v to is convertible to only one of the types in v, you would be able to simply write, v = x. However, this is not possible when you have multiple int types in the same variant so I had to use emplace instead, hence being explicit about the type.

On 4 Feb 2018, at 15:54, Alexandre Plateau notifications@github.com wrote:

Hi,

I am trying to store size_t as well as int64_t, double, bool, string in a variant. Storing the 4 last types work fine, but I get a bad_variant_access when trying to get/set the size_t with this code :

include

include

define MPARK_EXCEPTIONS

include <mpark/variant.hpp>

using namespace std; // i know it's bad, it's just for testing

int main() { mpark::variant v<int64_t, double, bool, string, size_t>; mpakr::get(v) = 15; // right there return 0; } — You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/mpark/variant/issues/40, or mute the thread https://github.com/notifications/unsubscribe-auth/AFrgCvtjMEFh28Z7iQTwN9tnzHIofVKkks5tRdLLgaJpZM4R4nUe.

SuperFola commented 6 years ago

Even this way, I am still getting a bad_variant_access :/

mpark commented 6 years ago

@SuperFola: What configuration are you using? @SaadAttieh's snippet works fine for me: https://wandbox.org/permlink/GFYehONmvuc7cByX

SuperFola commented 6 years ago

I am using gnu gcc (mingw 4.8), with -Wall -std=c++14 -g on Windows (I want to add that I had to add the define MPARK_EXCEPTIONS to be able to see the error, otherwise I would just get a terminate without an active exception).

mpark commented 6 years ago

@SuperFola: Does this issue only arise with size_t in specific..? or are you able to reproduce it with any type?

SuperFola commented 6 years ago

Using size_t or uint32_t seems to be a problem, I can try others things (it seems to be a problem only with unsigned integers type) if you want :)

edit :

#include <iostream>
#include <cstdint>

#define MPARK_EXCEPTIONS
#include "variant.hpp"

using namespace std;

int main()
{
    mpark::variant<
        int8_t,  int16_t,  int32_t,  int64_t, uint8_t, uint16_t, /*uint32_t,*/ uint64_t, size_t
    > v;

    cout << 1 << flush; mpark::get<int8_t>(v)   = 15;
    cout << 2 << flush; mpark::get<int16_t>(v)  = 15;
    cout << 3 << flush; mpark::get<int32_t>(v)  = 15;
    cout << 4 << flush; mpark::get<int64_t>(v)  = 15;
    cout << 5 << flush; mpark::get<uint8_t>(v)  = 15;
    cout << 6 << flush; mpark::get<uint16_t>(v) = 15;
    // if I add this line, it refuses to compile
    // cout << 7 << flush; mpark::get<uint32_t>(v) = 15;
    cout << 8 << flush; mpark::get<uint64_t>(v) = 15;
    // same here as long as uint32_t is in the variant
    cout << 9 << flush; mpark::get<size_t>(v)   = 15;

    return 0;
}

this code compiles but is throwing a bad variant access

12terminate called after throwing an instance of 'mpark::bad_variant_access'
  what():  bad_variant_access

I tried to comment some of the "tests" and it seems to be a problem to have different integers type in the variant :

    mpark::variant<
        int8_t,  int16_t,  int32_t,  int64_t, uint8_t, uint16_t, /*uint32_t,*/ uint64_t /*size_t*/
    > v;

    cout << 1 << flush; mpark::get<int8_t>(v)   = 15;
    // cout << 2 << flush; mpark::get<int16_t>(v)  = 15;
    // cout << 3 << flush; mpark::get<int32_t>(v)  = 15;
    cout << 4 << flush; mpark::get<int64_t>(v)  = 15;
    cout << 5 << flush; mpark::get<uint8_t>(v)  = 15;
    cout << 6 << flush; mpark::get<uint16_t>(v) = 15;
    // if I add this line, it refuses to compile
    // cout << 7 << flush; mpark::get<uint32_t>(v) = 15;
    cout << 8 << flush; mpark::get<uint64_t>(v) = 15;
    // same here as long as uint32_t is in the variant
    //cout << 9 << flush; mpark::get<size_t>(v)   = 15;

    return 0;

still throws a bad_variant_access :/

mpark commented 5 years ago

I'm going to close this for now since MinGW is not a distro that I'm officially supporting at this point. If there are enough requests for MinGW support going forward, I'll perhaps invest more time.