Skip to content

union fails 'is_base_of' assert #1685

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
danpf opened this issue Feb 5, 2019 · 1 comment
Closed

union fails 'is_base_of' assert #1685

danpf opened this issue Feb 5, 2019 · 1 comment

Comments

@danpf
Copy link

danpf commented Feb 5, 2019

I'm trying to bind a union with pybind11 and I'm getting a strange error. I'm not sure if i'm hitting a limitation of pybind11, or i'm implementing this incorrectly. Could anyone let me know if I'm implementing this incorrectly or if this is a limitation of pybind11? It looks like it is failing on

cl.def_readwrite("boolean", &union_type::boolean);

I'll note that I'm getting a similar error with

Issue description

union fails 'is_base_of' assert

Reproducible example code


#include <iostream>
#include <pybind11/pybind11.h>

namespace py = pybind11;

union union_type {
	 bool boolean;
	 uint64_t u64;
	 int64_t  i64;
	 double   f64;
};

PYBIND11_MODULE(example, m) {
	union_type a;
	py::class_<union_type> cl(m, "union_type", "");
	cl.def( pybind11::init( [](union_type const &o){ return new union_type(o); } ) );
	cl.def( pybind11::init( [](){ return new union_type(); } ) );
	cl.def_readwrite("boolean", &union_type::boolean);
	cl.def_readwrite("u64", &union_type::u64);
	cl.def_readwrite("i64", &union_type::i64);
	cl.def_readwrite("f64", &union_type::f64);
}

Error

pybind11/pybind11.h: In instantiation of ‘pybind11::class_<type_, options>& pybind11::class_<type_, options>::def_readwrite(const char*, D C::*, const Extra& ...) \
[with C = union_type; D = bool; Extra = {}; type_ = union_type; options = {std::shared_ptr<union_type>}]’:
mytest.cpp:35:59:   required from here
python3.7m/pybind11/pybind11.h:1161:9: error: static assertion failed: def_readwrite() requires a class member (or base class member
)
         static_assert(std::is_base_of<C, type>::value, "def_readwrite() requires a class member (or base class member)");
         ^~~~~~~~~~~~~

compiled with:

c++ -O3 -Wall -shared -std=c++11 -fPIC `python3 -m pybind11 --includes` mytest.cpp -o example`python3-config --extension-suffix`
@rolandd
Copy link
Contributor

rolandd commented Feb 20, 2019

I wonder if the assertion in pybind11 should be

static_assert(std::is_same<C, type>::value || std::is_base_of<C, type>::value, ...

the C++ standard says that is_base_of will be true if the two types are the same non-union type.

All the pybind stuff will work with unions, so I think the assertion is just being too strict.

rolandd added a commit to rolandd/pybind11 that referenced this issue Feb 20, 2019
In def_readonly and def_readwrite, there is an assertion that the member comes
from the class or a base class:

    static_assert(std::is_base_of<C, type>::value, "...");

However, if C and type are the same type, is_base_of will still only be true
if they are the same _non-union_ type.  This means we can't define accessors
for the members of a union type because of this assertion.

Update the assertion to test

    std::is_same<C, type>::value || std::is_base_of<C, type>::value

which will allow union types, or members of base classes.
rolandd added a commit to rolandd/pybind11 that referenced this issue Feb 24, 2019
In def_readonly and def_readwrite, there is an assertion that the member comes
from the class or a base class:

    static_assert(std::is_base_of<C, type>::value, "...");

However, if C and type are the same type, is_base_of will still only be true
if they are the same _non-union_ type.  This means we can't define accessors
for the members of a union type because of this assertion.

Update the assertion to test

    std::is_same<C, type>::value || std::is_base_of<C, type>::value

which will allow union types, or members of base classes.

Also add a basic unit test for accessing unions.
rolandd added a commit to rolandd/pybind11 that referenced this issue Feb 24, 2019
In def_readonly and def_readwrite, there is an assertion that the member comes
from the class or a base class:

    static_assert(std::is_base_of<C, type>::value, "...");

However, if C and type are the same type, is_base_of will still only be true
if they are the same _non-union_ type.  This means we can't define accessors
for the members of a union type because of this assertion.

Update the assertion to test

    std::is_same<C, type>::value || std::is_base_of<C, type>::value

which will allow union types, or members of base classes.

Also add a basic unit test for accessing unions.
rolandd added a commit to rolandd/pybind11 that referenced this issue Jun 10, 2019
In def_readonly and def_readwrite, there is an assertion that the member comes
from the class or a base class:

    static_assert(std::is_base_of<C, type>::value, "...");

However, if C and type are the same type, is_base_of will still only be true
if they are the same _non-union_ type.  This means we can't define accessors
for the members of a union type because of this assertion.

Update the assertion to test

    std::is_same<C, type>::value || std::is_base_of<C, type>::value

which will allow union types, or members of base classes.

Also add a basic unit test for accessing unions.
rolandd added a commit to rolandd/pybind11 that referenced this issue Jun 11, 2019
In def_readonly and def_readwrite, there is an assertion that the member comes
from the class or a base class:

    static_assert(std::is_base_of<C, type>::value, "...");

However, if C and type are the same type, is_base_of will still only be true
if they are the same _non-union_ type.  This means we can't define accessors
for the members of a union type because of this assertion.

Update the assertion to test

    std::is_same<C, type>::value || std::is_base_of<C, type>::value

which will allow union types, or members of base classes.

Also add a basic unit test for accessing unions.
wjakob pushed a commit that referenced this issue Jun 11, 2019
In def_readonly and def_readwrite, there is an assertion that the member comes
from the class or a base class:

    static_assert(std::is_base_of<C, type>::value, "...");

However, if C and type are the same type, is_base_of will still only be true
if they are the same _non-union_ type.  This means we can't define accessors
for the members of a union type because of this assertion.

Update the assertion to test

    std::is_same<C, type>::value || std::is_base_of<C, type>::value

which will allow union types, or members of base classes.

Also add a basic unit test for accessing unions.
wjakob pushed a commit that referenced this issue Jun 11, 2019
In def_readonly and def_readwrite, there is an assertion that the member comes
from the class or a base class:

    static_assert(std::is_base_of<C, type>::value, "...");

However, if C and type are the same type, is_base_of will still only be true
if they are the same _non-union_ type.  This means we can't define accessors
for the members of a union type because of this assertion.

Update the assertion to test

    std::is_same<C, type>::value || std::is_base_of<C, type>::value

which will allow union types, or members of base classes.

Also add a basic unit test for accessing unions.
@wjakob wjakob closed this as completed Jun 24, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants