Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::atomic as class member: use of deleted function error when using boost/python.hpp

Tags:

c++

boost

Other seemingly related questions appear to be resolved by doing direct initialization of the atomic:

std::atomic_uint32_t v1{0};

However, when I have a std::atomic variable as a class member I still get a "use of deleted function" error. I also only get the error when using Boost Python to wrap up my class so that it's callable from Python. I assume this is because Boost Python is applying additional compilation rules rather than some issue with Boost Python.

AtomicTest.cpp

#include "AtomicTest.h"
#include <boost/python.hpp>
using namespace boost::python;

void AtomicTest::init()
{
    printf("Atomic test\n");
}


BOOST_PYTHON_MODULE(atomicTest)
{
    class_<AtomicTest>("AtomicTest")
    .def("init", &AtomicTest::init)
    ;
};

AtomicTest.h

#ifndef ATOMICTEST_ATOMICTEST_H
#define ATOMICTEST_ATOMICTEST_H

#include <atomic>

class AtomicTest
{
public:
    void init();
    std::atomic_uint32_t v1{0};
};


#endif //ATOMICTEST_ATOMICTEST_H

Build Log:

In file included from /usr/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:52:0,
                 from /usr/include/boost/python/object/value_holder.hpp:46,
                 from /usr/include/boost/python/object/class_metadata.hpp:14,
                 from /usr/include/boost/python/class.hpp:23,
                 from /usr/include/boost/python.hpp:18,
                 from /home/tb/CLionProjects/atomicTest/AtomicTest.cpp:6:
/usr/include/boost/python/object/value_holder.hpp: In instantiation of ‘boost::python::objects::value_holder<Value>::value_holder(PyObject*, A0) [with A0 = boost::reference_wrapper<const AtomicTest>; Value = AtomicTest; PyObject = _object]’:
/usr/include/boost/python/object/make_instance.hpp:72:16:   required from ‘static Holder* boost::python::objects::make_instance<T, Holder>::construct(void*, PyObject*, boost::reference_wrapper<const T>) [with T = AtomicTest; Holder = boost::python::objects::value_holder<AtomicTest>; PyObject = _object]’
/usr/include/boost/python/object/make_instance.hpp:46:31:   required from ‘static PyObject* boost::python::objects::make_instance_impl<T, Holder, Derived>::execute(Arg&) [with Arg = const boost::reference_wrapper<const AtomicTest>; T = AtomicTest; Holder = boost::python::objects::value_holder<AtomicTest>; Derived = boost::python::objects::make_instance<AtomicTest, boost::python::objects::value_holder<AtomicTest> >; PyObject = _object]’
/usr/include/boost/python/object/class_wrapper.hpp:29:37:   required from ‘static PyObject* boost::python::objects::class_cref_wrapper<Src, MakeInstance>::convert(const Src&) [with Src = AtomicTest; MakeInstance = boost::python::objects::make_instance<AtomicTest, boost::python::objects::value_holder<AtomicTest> >; PyObject = _object]’
/usr/include/boost/python/converter/as_to_python_function.hpp:27:61:   required from ‘static PyObject* boost::python::converter::as_to_python_function<T, ToPython>::convert(const void*) [with T = AtomicTest; ToPython = boost::python::objects::class_cref_wrapper<AtomicTest, boost::python::objects::make_instance<AtomicTest, boost::python::objects::value_holder<AtomicTest> > >; PyObject = _object]’
/usr/include/boost/python/to_python_converter.hpp:83:9:   [ skipping 2 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/include/boost/python/object/class_metadata.hpp:227:55:   required from ‘static void boost::python::objects::class_metadata<T, X1, X2, X3>::register_aux2(T2*, Callback) [with T2 = AtomicTest; Callback = boost::integral_constant<bool, false>; T = AtomicTest; X1 = boost::python::detail::not_specified; X2 = boost::python::detail::not_specified; X3 = boost::python::detail::not_specified]’
/usr/include/boost/python/object/class_metadata.hpp:218:38:   required from ‘static void boost::python::objects::class_metadata<T, X1, X2, X3>::register_aux(void*) [with T = AtomicTest; X1 = boost::python::detail::not_specified; X2 = boost::python::detail::not_specified; X3 = boost::python::detail::not_specified]’
/usr/include/boost/python/object/class_metadata.hpp:204:37:   required from ‘static void boost::python::objects::class_metadata<T, X1, X2, X3>::register_() [with T = AtomicTest; X1 = boost::python::detail::not_specified; X2 = boost::python::detail::not_specified; X3 = boost::python::detail::not_specified]’
/usr/include/boost/python/class.hpp:450:28:   required from ‘void boost::python::class_<T, X1, X2, X3>::initialize(const DefVisitor&) [with DefVisitor = boost::python::init<>; W = AtomicTest; X1 = boost::python::detail::not_specified; X2 = boost::python::detail::not_specified; X3 = boost::python::detail::not_specified]’
/usr/include/boost/python/class.hpp:583:5:   required from ‘boost::python::class_<T, X1, X2, X3>::class_(const char*, const char*) [with W = AtomicTest; X1 = boost::python::detail::not_specified; X2 = boost::python::detail::not_specified; X3 = boost::python::detail::not_specified]’
/home/tb/CLionProjects/atomicTest/AtomicTest.cpp:17:48:   required from here
/usr/include/boost/python/object/value_holder.hpp:133:13: error: use of deleted function ‘AtomicTest::AtomicTest(const AtomicTest&)’
             BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_UNFORWARD_LOCAL, nil)
             ^
In file included from /home/tb/CLionProjects/atomicTest/AtomicTest.cpp:5:0:
/home/tb/CLionProjects/atomicTest/AtomicTest.h:10:7: note: ‘AtomicTest::AtomicTest(const AtomicTest&)’ is implicitly deleted because the default definition would be ill-formed:
 class AtomicTest
       ^~~~~~~~~~
/home/tb/CLionProjects/atomicTest/AtomicTest.h:10:7: error: use of deleted function ‘std::atomic<unsigned int>::atomic(const std::atomic<unsigned int>&)’
In file included from /home/tb/CLionProjects/atomicTest/AtomicTest.h:8:0,
                 from /home/tb/CLionProjects/atomicTest/AtomicTest.cpp:5:
/usr/include/c++/7/atomic:691:7: note: declared here
       atomic(const atomic&) = delete;
like image 565
tyler124 Avatar asked May 12 '26 16:05

tyler124


1 Answers

When the Python interface initializes its objects that will be available from Python it copies your object. Since your class has the default copy constructor, it copies each field as well, and atomic objects do not have copy constructors (or assignments), and for good reason.

The way to go here is to tell boost not to use copies, using noncopyable (have to search there). This question has this as an example boost::python: compilation fails because copy constructor is private, and in your case you need to change the class_ definition:

class_<AtomicTest, boost::noncopyable>("AtomicTest")

Optionally you could also hold your atomic number in a (shared) pointer, so that all copies look at the same one. This often makes sense in some designs where multiple objects are synchronized to the same counter:

class AtomicTest
{
public:
    AtomicTest() : v1(std::make_shared<std::atomic_uint32_t>(0)) {}
    void init();
    std::shared_ptr<std::atomic_uint32_t> v1;
};

If your use case though is a single object counting by itself though, then noncopyable is probably more suitable.

like image 134
kabanus Avatar answered May 14 '26 06:05

kabanus



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!