Search code examples
c++c++17c++20cppyycling

cppyy cling fails on class member initialization if =default constructor was declared


I am trying to use cppyy (installed with STDCXX=17 MAKE_NPROCS=32 pip install --verbose cppyy --no-binary=cppyy-cling) for an existing header-only library that declares =default constructor together with member initialization, similar to the example:

import os
os.environ["STDCXX"] = "17"
os.environ["EXTRA_CLING_ARGS"] = "-std=c++17"
import cppyy_backend.loader as l
l.set_cling_compile_options(True)

import cppyy
cppyy.cppdef("""
class A {
    public:
        A() = default; // error in c++20 but ok in c++17
        int a;
};
int b() {
    A a{17};
    return a.a;
};
""")
print(cppyy.gbl.b()) # expect "17"

Execution crashes with

note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const A' for 1st argument
class A
      ^
note: candidate constructor not viable: requires 0 arguments, but 1 was provided
        A() = default;

This would be correct behavior for c++20 but I've tried to enforce c++17. Does anyone have an idea what is missed here?

root-config --cxx points to g++ 8.4.0


Solution

  • The code above should worked.... Note that there's no reason to rebuild cppyy-cling to simply change C++ standard. It looks to me like you have a c++20 precompiled header on your system, however. How, I don't know, b/c rebuilding like the above should have baked in C++17, but the fact that you mention root-config suggest to me that you have a mixed ROOT/cppyy installation, which is in general a bad idea. The ROOT team forked cppyy but hasn't kept their fork in sync, so the PIP version and the ROOT version will clash and that is probably the source of the problems observed.

    That said, if you run once with the envars CLING_REBUILD_PCH=1 and EXTRA_CLING_ARGS (as appropriate) set, then it should work as the former forces rebuilding of the PCH. (Setting STDCXX doesn't do anything outside of the build/install process.)

    You can check standard flags taken from the build/install with cling-config:

    $ cling-config --cppflags
    

    which will mention C++17 if build like above, C++20 otherwise; and you can check the version baked into the PCH with:

    $ python -c 'import cppyy; cppyy.cppexec("std::cerr << __cplusplus << std::endl;")'
    

    Aside, MAKE_NPROCS=32 is just an example in the docs. Make sure that you actually have 32 cores before setting that variable. (If you don't set it, the total number of available processors will be used.)