Skip to content
This repository has been archived by the owner on Jan 7, 2019. It is now read-only.

Register: error: use of deleted function #124

Closed
strongly-typed opened this issue May 8, 2016 · 6 comments · Fixed by #143
Closed

Register: error: use of deleted function #124

strongly-typed opened this issue May 8, 2016 · 6 comments · Fixed by #143

Comments

@strongly-typed
Copy link
Member

Trying to use CtrlMeas::Mode1 | CtrlMeas::Mode0 with register.hpp in the plain blink example:

#include <xpcc/architecture/platform.hpp>
#include <xpcc/architecture/interface/register.hpp>

using namespace Board;

namespace xpcc
{

struct bme280
{
protected:

    enum class
    CtrlMeas : uint8_t
    {
        OSRS_T2 = xpcc::Bit7,
        OSRS_T1 = xpcc::Bit6,
        OSRS_T0 = xpcc::Bit5,
        OSRS_P2 = xpcc::Bit4,
        OSRS_P1 = xpcc::Bit3,
        OSRS_P0 = xpcc::Bit2,
        Mode1   = xpcc::Bit1,
        Mode0   = xpcc::Bit0,
    };
    XPCC_FLAGS8(CtrlMeas);

    enum class
    Mode : uint8_t
    {
        Sleep = 0,
        Forced = CtrlMeas::Mode0,
        Normal = CtrlMeas::Mode1 | CtrlMeas::Mode0,
    };

};

} // xpcc namespace

// ----------------------------------------------------------------------------
int
main()
{
    while (true)
        {}
    return 0;
}

With gcc version 5.2.1 20151202

arm-none-eabi-g++ -v
Using built-in specs.
COLLECT_GCC=arm-none-eabi-g++
COLLECT_LTO_WRAPPER=/opt/homebrew-cask/Caskroom/gcc-arm-embedded/5_2-2015q4,20151219/gcc-arm-none-eabi-5_2-2015q4/bin/../lib/gcc/arm-none-eabi/5.2.1/lto-wrapper
Target: arm-none-eabi
Configured with: /Users/build/workspace/GCC-5-0-build_build-toolchain-mac/gcc-arm-none-eabi-5_2-2015q4-20151219/src/gcc/configure --target=arm-none-eabi --prefix=/Users/build/workspace/GCC-5-0-build_build-toolchain-mac/gcc-arm-none-eabi-5_2-2015q4-20151219/install-native --libexecdir=/Users/build/workspace/GCC-5-0-build_build-toolchain-mac/gcc-arm-none-eabi-5_2-2015q4-20151219/install-native/lib --infodir=/Users/build/workspace/GCC-5-0-build_build-toolchain-mac/gcc-arm-none-eabi-5_2-2015q4-20151219/install-native/share/doc/gcc-arm-none-eabi/info --mandir=/Users/build/workspace/GCC-5-0-build_build-toolchain-mac/gcc-arm-none-eabi-5_2-2015q4-20151219/install-native/share/doc/gcc-arm-none-eabi/man --htmldir=/Users/build/workspace/GCC-5-0-build_build-toolchain-mac/gcc-arm-none-eabi-5_2-2015q4-20151219/install-native/share/doc/gcc-arm-none-eabi/html --pdfdir=/Users/build/workspace/GCC-5-0-build_build-toolchain-mac/gcc-arm-none-eabi-5_2-2015q4-20151219/install-native/share/doc/gcc-arm-none-eabi/pdf --enable-languages=c,c++ --enable-plugins --disable-decimal-float --disable-libffi --disable-libgomp --disable-libmudflap --disable-libquadmath --disable-libssp --disable-libstdcxx-pch --disable-nls --disable-shared --disable-threads --disable-tls --with-gnu-as --with-gnu-ld --with-newlib --with-headers=yes --with-python-dir=share/gcc-arm-none-eabi --with-sysroot=/Users/build/workspace/GCC-5-0-build_build-toolchain-mac/gcc-arm-none-eabi-5_2-2015q4-20151219/install-native/arm-none-eabi --build=x86_64-apple-darwin10 --host=x86_64-apple-darwin10 --with-gmp=/Users/build/workspace/GCC-5-0-build_build-toolchain-mac/gcc-arm-none-eabi-5_2-2015q4-20151219/build-native/host-libs/usr --with-mpfr=/Users/build/workspace/GCC-5-0-build_build-toolchain-mac/gcc-arm-none-eabi-5_2-2015q4-20151219/build-native/host-libs/usr --with-mpc=/Users/build/workspace/GCC-5-0-build_build-toolchain-mac/gcc-arm-none-eabi-5_2-2015q4-20151219/build-native/host-libs/usr --with-isl=/Users/build/workspace/GCC-5-0-build_build-toolchain-mac/gcc-arm-none-eabi-5_2-2015q4-20151219/build-native/host-libs/usr --with-cloog=/Users/build/workspace/GCC-5-0-build_build-toolchain-mac/gcc-arm-none-eabi-5_2-2015q4-20151219/build-native/host-libs/usr --with-libelf=/Users/build/workspace/GCC-5-0-build_build-toolchain-mac/gcc-arm-none-eabi-5_2-2015q4-20151219/build-native/host-libs/usr --with-host-libstdcxx='-static-libgcc -Wl,-lstdc++ -lm' --with-pkgversion='GNU Tools for ARM Embedded Processors' --with-multilib-list=armv6-m,armv7-m,armv7e-m,armv7-r,armv8-m.base,armv8-m.main
Thread model: single
gcc version 5.2.1 20151202 (release) [ARM/embedded-5-branch revision 231848] (GNU Tools for ARM Embedded Processors)

yields to

Compiling C++: /Users/usr/Dev/xpcc/build/stm32f4_discovery/blink/main.o
    main.cpp:32:40: error: use of deleted function 'constexpr xpcc::Register<T>::operator unsigned char() const [with T = unsigned char]'
       Normal = CtrlMeas::Mode1 | CtrlMeas::Mode0,
                                            ^
    In file included from /Users/usr/Dev/xpcc/src/xpcc/architecture/interface.hpp:107:0,
                     from /Users/usr/Dev/xpcc/build/stm32f4_discovery/blink/libxpcc/src/xpcc/architecture/../../../generated_platform/driver/can/generic/can_bit_timings.hpp:13,
                     from /Users/usr/Dev/xpcc/build/stm32f4_discovery/blink/libxpcc/src/xpcc/architecture/../../../generated_platform/drivers.hpp:36,
                     from /Users/usr/Dev/xpcc/build/stm32f4_discovery/blink/libxpcc/src/xpcc/architecture/platform.hpp:19,
                     from main.cpp:1:
    /Users/usr/Dev/xpcc/src/xpcc/architecture/interface/register.hpp:264:12: note: declared here
      constexpr operator unsigned char() const = delete;
                ^
    scons: *** [/Users/usr/Dev/xpcc/build/stm32f4_discovery/blink/main.o] Error 1
    scons: building terminated because of errors.

IMHO the usage is the same as in this example but is not covered by the unittest. Shall the example work?

When leaving out the | CtrlMeas::Mode0 part the compiler is happy.

It shall be noted that XPCC_FLAGS8 is only usable inside a struct or class, so putting a struct around your register definitions is necessary.

@salkinium
Copy link
Member

Hm, I think you have to cast it to int before ORing ie. int(CtrlMeas::Mode1) | int(CtrlMeas::Mode0).

I ran into this problem before, I couldn't find a solution for it back then.
It has something to do with the constness of results from operator overloading. But they are already all constexpr, I don't know what more I could do to make it more "const"y.

@salkinium
Copy link
Member

salkinium commented May 8, 2016

It shall be noted that XPCC_FLAGS8 is only usable inside a struct or class, so putting a struct around your register definitions is necessary.

See the workaround for outside a struct or class:

typedef xpcc::Flags8<Enum> Enum_t;
XPCC_TYPE_FLAGS(Enum_t);

The only difference is a friend classifier, which I find stupid and frustrating.

Unfortunately C++ sucks here, because even though it's a enumclass, it doesn't get any of the first-class support that regular classes or types get. Especially the operator overloading is weird and not everything is allowed (casting operators for example).

@strongly-typed
Copy link
Member Author

When I change

v1 = Test3::Bit | Config2(Config::Three) | Config0(Config::Two);

to

v1 = Config2(Config::Three) | Config0(Config::Two);

With g++-5

g++-5 -o /Users/usr/Dev/xpcc/build/unittest_hosted/xpcc/architecture/interface/test/register_test.o -c -std=c++11 -Woverloaded-virtual -funsigned-char -Wall -Wextra -Wundef -ggdb -DBASENAME=register_test.cpp -DXPCC__CLOCK_TESTMODE=1 -I. -I/Users/usr/Dev/xpcc/ext -I/Users/usr/Dev/xpcc/build/unittest_hosted/libxpcc/src xpcc/architecture/interface/test/register_test.cpp
    xpcc/architecture/interface/test/register_test.cpp: In member function 'void RegisterTest::testConfigurations()':
    xpcc/architecture/interface/test/register_test.cpp:271:30: error: ambiguous overload for 'operator|' (operand types are 'xpcc::testing::Config2 {aka xpcc::Configuration<xpcc::Flags<xpcc::testing::Test3, unsigned char>, xpcc::testing::Config, 3u, 2u>}' and 'xpcc::testing::Config0 {aka xpcc::Configuration<xpcc::Flags<xpcc::testing::Test3, unsigned char>, xpcc::testing::Config, 3u>}')
      v1 = Config2(Config::Three) | Config0(Config::Two);

Same with g++-6

g++-6 -o /Users/usr/Dev/xpcc/build/unittest_hosted/xpcc/architecture/interface/test/register_test.o -c -std=c++11 -Woverloaded-virtual -funsigned-char -Wall -Wextra -Wundef -ggdb -DBASENAME=register_test.cpp -DXPCC__CLOCK_TESTMODE=1 -I. -I/Users/usr/Dev/xpcc/ext -I/Users/usr/Dev/xpcc/build/unittest_hosted/libxpcc/src xpcc/architecture/interface/test/register_test.cpp
xpcc/architecture/interface/test/register_test.cpp: In member function 'void RegisterTest::testConfigurations()':
xpcc/architecture/interface/test/register_test.cpp:271:30: error: ambiguous overload for 'operator|' (operand types are 'xpcc::testing::Config2 {aka xpcc::Configuration<xpcc::Flags<xpcc::testing::Test3, unsigned char>, xpcc::testing::Config, 3u, 2u>}' and 'xpcc::testing::Config0 {aka xpcc::Configuration<xpcc::Flags<xpcc::testing::Test3, unsigned char>, xpcc::testing::Config, 3u>}')
  v1 = Config2(Config::Three) | Config0(Config::Two);
       ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~

Apple LLVM version 7.3.0 (clang-703.0.31)

g++ -o /Users/usr/Dev/xpcc/build/unittest_hosted/xpcc/architecture/interface/test/register_test.o -c -std=c++11 -Woverloaded-virtual -funsigned-char -Wall -Wextra -Wundef -ggdb -DBASENAME=register_test.cpp -DXPCC__CLOCK_TESTMODE=1 -I. -I/Users/usr/Dev/xpcc/ext -I/Users/usr/Dev/xpcc/build/unittest_hosted/libxpcc/src xpcc/architecture/interface/test/register_test.cpp
xpcc/architecture/interface/test/register_test.cpp:271:30: error: use of overloaded operator '|' is ambiguous (with operand types 'Config2' (aka 'Configuration<xpcc::Flags<xpcc::testing::Test3,
      unsigned char>, xpcc::testing::Config, Bit1 | Bit0, 2>') and 'Config0' (aka 'Configuration<xpcc::Flags<xpcc::testing::Test3, unsigned char>, xpcc::testing::Config, Bit1 | Bit0>'))
        v1 = Config2(Config::Three) | Config0(Config::Two);
             ~~~~~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~

@salkinium
Copy link
Member

salkinium commented May 15, 2016

This isn't a compiler issue, Configs and Values just can't be ORed, the operators are missing.
Config0(Config::Two) | Test3::Bit won't work either, cos the Configuration has no operator to OR with Flags.

I'm not sure why this didn't come up earlier. This is definitely a design bug.

@strongly-typed
Copy link
Member Author

strongly-typed commented Jun 24, 2016

The initial examples given above still does not work. Or'ing Flags with Flags still does not work.

main.cpp:32:46: error: use of deleted function 'constexpr xpcc::Register<T>::operator unsigned char() const [with T = unsigned char]'
         Normal = CtrlMeas::Mode1 | CtrlMeas::Mode0,
                                              ^
 /Users/usr/tmp/xpcc3/src/xpcc/architecture/interface/register.hpp:264:12: note: declared here
   constexpr operator unsigned char() const = delete;

Same with gcc version 4.9.3 20150529 on Linux

main.cpp:32:46: error: 'constexpr xpcc::bme280::CtrlMeas_t xpcc::operator|(const EnumType&, const EnumType&)' called in a constant expression
         Normal = CtrlMeas::Mode1 | CtrlMeas::Mode0,
                                              ^
   main.cpp:32:46: error: enumerator value for 'Normal' is not an integer constant

@salkinium
Copy link
Member

ORing the flags will create a value of the type CtrlMeas_t that's not castable to uint8_t, the underlying type of Mode.

You can either do cast to an integer int(CtrlMeas::Mode1 | CtrlMeas::Mode0) or access the underlying type (CtrlMeas::Mode1 | CtrlMeas::Mode0).value. Both versions suck, but I'm afraid this is not solvable any other way :-(

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants