1

I'm testing possibility to translate simulation done in Processing into C++. But something strange happened:

class World {
  public:
    sarray<pAnt>    dummy1 { new array<pAnt>(10) };//OK
    sarray<pAnt>    dummy2 = new array<pAnt>(10);  //Compiler error?!?!?!*
    smatrix<pAnt>   dummyWorld1 { new matrix<pAnt>(100,100) };//OK
    smatrix<pAnt>   dummyWorld2 = new matrix<pAnt>(100,100);//OK
    smatrix<int>    ants = new matrix<int>(50,2);// OK
...
};
  • ERROR:

    /data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/klasaWorld.pde.cpp:27:

    error: cannot bind non-const lvalue reference of type ‘Processing::sarrayProcessing::ptr<Ant >&’ to an rvalue of type ‘Processing::sarrayProcessing::ptr<Ant >’

     sarray<pAnt>    dummy2 = new array<pAnt>(10) ;//Compiler error?!?
    

"Verbose" compiler output:

[1/2 3.5/sec] Building CXX object CMakeFiles/MROWKI_0.1_once.dir/data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/project_at_once.cpp.o FAILED: CMakeFiles/MROWKI_0.1_once.dir/data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/project_at_once.cpp.o /usr/bin/g++ -DDEF_MAXTHREADS=16 -DMULTITR -DVERSION_NUM=0.1 -I/data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc -I/home/borkowsk/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/../../scripts/../lib/include -I/data/wb/SCC/__working_copies/symShell2/WBRTM_Linux -I/data/wb/SCC/__working_copies/symShell2/WBRTM_Linux/INCLUDE --verbose -std=c++11 -pthread -MD -MT CMakeFiles/MROWKI_0.1_once.dir/data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/project_at_once.cpp.o -MF CMakeFiles/MROWKI_0.1_once.dir/data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/project_at_once.cpp.o.d -o CMakeFiles/MROWKI_0.1_once.dir/data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/project_at_once.cpp.o -c /data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/project_at_once.cpp Using built-in specs. COLLECT_GCC=/usr/bin/g++ OFFLOAD_TARGET_NAMES=nvptx-none OFFLOAD_TARGET_DEFAULT=1 Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu 7.5.0-3ubuntu1~18.04' --with-bugurl=file:///usr/share/doc/gcc-7/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-7 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) COLLECT_GCC_OPTIONS='-D' 'DEF_MAXTHREADS=16' '-D' 'MULTITR' '-D' 'VERSION_NUM=0.1' '-I' '/data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc' '-I' '/home/borkowsk/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/../../scripts/../lib/include' '-I' '/data/wb/SCC/__working_copies/symShell2/WBRTM_Linux' '-I' '/data/wb/SCC/__working_copies/symShell2/WBRTM_Linux/INCLUDE' '-v' '-std=c++11' '-pthread' '-MD' '-MT' 'CMakeFiles/MROWKI_0.1_once.dir/data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/project_at_once.cpp.o' '-MF' 'CMakeFiles/MROWKI_0.1_once.dir/data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/project_at_once.cpp.o.d' '-o' 'CMakeFiles/MROWKI_0.1_once.dir/data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/project_at_once.cpp.o' '-c' '-shared-libgcc' '-mtune=generic' '-march=x86-64' /usr/lib/gcc/x86_64-linux-gnu/7/cc1plus -quiet -v -I /data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc -I /home/borkowsk/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/../../scripts/../lib/include -I /data/wb/SCC/__working_copies/symShell2/WBRTM_Linux -I /data/wb/SCC/__working_copies/symShell2/WBRTM_Linux/INCLUDE -imultiarch x86_64-linux-gnu -MD CMakeFiles/MROWKI_0.1_once.dir/data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/project_at_once.cpp.d -MF CMakeFiles/MROWKI_0.1_once.dir/data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/project_at_once.cpp.o.d -MT CMakeFiles/MROWKI_0.1_once.dir/data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/project_at_once.cpp.o -D_GNU_SOURCE -D_REENTRANT -D DEF_MAXTHREADS=16 -D MULTITR -D VERSION_NUM=0.1 /data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/project_at_once.cpp -quiet -dumpbase project_at_once.cpp -mtune=generic -march=x86-64 -auxbase-strip CMakeFiles/MROWKI_0.1_once.dir/data/wb/SCC/__working_copies/Processing2C/PROJECTS/MROWKI/cppsrc/project_at_once.cpp.o -std=c++11 -version -fstack-protector-strong -Wformat -Wformat-security -o /tmp/ccaH1ylE.s

GNU C++11 (Ubuntu 7.5.0-3ubuntu1~18.04) version 7.5.0 (x86_64-linux-gnu) compiled by GNU C version 7.5.0, GMP version 6.1.2, MPFR version 4.0.1, MPC version 1.1.0, isl version isl-0.19-GMP ^

Here is the problem extracted from my project. Looks like one line is guilty, but I don't understand why :-)

#include <memory>

namespace Processing
{
   
template<class T>
class ptr
{
      //std::shared_ptr<T> _ptr;
  public:
      ptr();
      ptr(ptr<T>&);
      //ptr(const ptr<T>&);//This removes the error, but can not be implemented properly!
};

template<class T>
class array
{     
      //T* content;
  public:
      ~array();
      array(size_t N);
};

template<class T>
class sarray
{     // When the following line is commented out the error disapper!
      // so what is missing in ptr<T> ?  
      ptr< array<T> > _arr;//opaque smart ptr to array
      //std::shared_ptr< array<T> > _arr;//std smart pointer is OK
  public:
      ~sarray(){}
      sarray(){}
      sarray(array<T>* tab);
      sarray<T>& operator = (array<T>* tab);
};

}

using namespace Processing;


void example()
{  
  sarray<bool>          test1 = new array<bool>(2);// Compiler error?
  sarray<bool>          test2;

  test2 = new array<bool>(2);//OK
  
  sarray<bool>   test3 { new array<bool>(2) };//OK      
}
  • After adding `sarray& sarray::operator = (array* tab);` it work in two stages, but not in one :-o `sarray test;` `//sarray test = new array(2);// Compiler error` `test = new array(2);//OK` `sarray test2 { new array(2) };//OK` `sarray dummy; //sarray dummy = new array(Side);// Compiler error dummy = new array(Side);//OK sarray dummy1 { new array(Side) };//OK` – Wojciech T. Borkowski Aug 08 '20 at 11:10
  • @rustyx - ok, I have compilable example, but how to provide the file here? – Wojciech T. Borkowski Aug 08 '20 at 12:27
  • 1
    @WojciechT.Borkowski "I have compilable example, but how to provide the file here?" - Just *edit* your question and paste the code. – Jesper Juhl Aug 08 '20 at 12:29
  • @WojciechT.Borkowski your new code is better, but still pretty far from a [MRE]. There is still a lot of code that is completely irrelevant to your issue and is just noise, making it harder for us (and you) to see the problem. Here is a proper [MRE]: https://godbolt.org/z/jqo7aq I've reach this by removing one by one lines I suspected had nothing to do with the error; if the error message stayed exactly the same I left the line deleted, if it changed the error message I put it back in. That's what you should do before posting here. Anyway I voted to reopen and will answer if it gets reopened. – bolov Aug 08 '20 at 14:52
  • I recommend to [edit] your question with the [MRE] I've given you in the beginning of the question. You want ppl to first see the [MRE], not have to scroll through 2 screens to get to it. Since you have a proper [MRE] I would also delete the long verbose error message and just post the simple error message from the [MRE]. Keep the things simple and relevant. – bolov Aug 08 '20 at 15:01
  • Error is connected with this line: `// When the following line is commented out the error disappers! ` ` ptr< array > _arr;//opaque smart ptr to array` – Wojciech T. Borkowski Aug 08 '20 at 17:54
  • I have removed code that may be irrelevant. But the remaining may be. – Wojciech T. Borkowski Aug 08 '20 at 18:06
  • OK. Your example is few line less :-) But any way I don't understand what happening. Why `sarray test3 { new array(2) };` is OK , but `sarray test1 = new array(2);` is not? The second syntax is important for me, because is much more similar to used always in Processing code. – Wojciech T. Borkowski Aug 08 '20 at 18:13
  • When I added second constructor to `ptr` : `ptr(const ptr&);` it starts to compile. But such a constructor is rather impossible for smart pointer. – Wojciech T. Borkowski Aug 08 '20 at 18:33
  • 2
    `X x = y;` is *copy-initialization*. It requires a copy constructor even if the copy is optimized away (until C++17). – rustyx Aug 08 '20 at 19:04
  • @rustyx - but in my code y is from `new arrar(...)` so in my opinion has type `array*`, so i has provided constructor `sarray(array* tab);`. It was compilable until I introduced the line `ptr< array > _arr;`. This error remains until I add second constructor to `ptr`: `ptr(const ptr& other);` This is strange because my code have nothing to do with `const` variables, and additionally implementation of smart pointer may need change something inside parmeter `other`. – Wojciech T. Borkowski Aug 08 '20 at 20:06

1 Answers1

2

sarray<pAnt> dummy2 = new array<pAnt>(10); is copy-initialization syntax.

Semantically it's similar to sarray<pAnt> dummy2( sarray<pAnt>( new array<pAnt>(10) ) ); (until C++17).

sarray has no user-defined copy constructor, so it gets an implicit one, which performs a member-wise copy.

The problem is, ptr, being one of the members, does have a user-defined copy constructor, ptr(ptr<T>&). Technically a copy constructor can take a non-const reference. In practice it is rarely useful, because a non-const reference will not bind to a temporary.

Hence the error - cannot bind non-const lvalue reference of type ‘...ptr<Ant>&’ to an rvalue of type ‘ptr<Ant>’

A solution could be simple - change the awkward copy constructor into a move-constructor ptr(ptr<T>&&) (or add one).

Additional note: it seems sarray has a user-defined destructor. According to the rule of 3/5/0 it probably needs a user-defined copy and/or move-constructor, too.

rustyx
  • 80,671
  • 25
  • 200
  • 267
  • Thank You. I'm a scientist, not a professional programmer, but I use C++ more than 20 years. Any way I have no idea that this kind of initialisation work so strange :-) – Wojciech T. Borkowski Aug 08 '20 at 21:30