lamdba и «error: capture of non-variable ‘type::v'»
|
От: |
niXman |
https://github.com/niXman |
Дата: | 17.07.12 13:22 | ||
Оценка: |
3 (1) |
привет.
следующий код. успешно компилится компиляторами версии 4.6.х, но выдает сабжевую ошибку при компиляции с использованием 4.7.1.
struct type {
type() {
[&v]() {}
}
int v;
};
int main() {
}
http://liveworkspace.org/code/fd17b80f11a60b81214bce4bedf99df9
код писал с использованием 4.6.3. кода написал дико много. при попытке собрать на 4.7.1 — получил тону ошибок %)
подскажите. как все же правильно захватывать переменные члены класса?
спасибо.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re: lamdba и «error: capture of non-variable ‘type::v'»
|
От: |
niXman |
https://github.com/niXman |
Дата: | 17.07.12 13:37 | ||
Оценка: |
так же, для всех лябмдов( %) ) выдается еще и ошибка: error: ‘this’ was not captured for this lambda function
код:
#include <iostream>
struct type {
type() {
[&v]() {std::cout<<v<<std::endl;}
}
int v;
};
int main() {
}
http://liveworkspace.org/code/01ae6ebb0527d6d900635e4bfa356c41
на 4.6.3 все гуд.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re: lamdba и «error: capture of non-variable ‘type::v'»
|
От: |
Abyx |
|
Дата: | 17.07.12 13:38 | ||
Оценка: |
Здравствуйте, niXman, Вы писали:
X>подскажите. как все же правильно захватывать переменные члены класса?
[this]
либо [=] — тогда this тоже захватится
In Zen We Trust
Re[2]: lamdba и «error: capture of non-variable ‘type::v'»
|
От: |
niXman |
https://github.com/niXman |
Дата: | 17.07.12 13:42 | ||
Оценка: |
Здравствуйте, Abyx, Вы писали:
A>
A>[this]
A>
т.е. захватывать мемберы нельзя? только this?
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[2]: lamdba и «error: capture of non-variable ‘type::v'»
|
От: |
niXman |
https://github.com/niXman |
Дата: | 17.07.12 13:44 | ||
Оценка: |
а this разве по умолчанию не захватывается?
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[3]: lamdba и «error: capture of non-variable ‘type::v'»
|
От: |
Abyx |
|
Дата: | 17.07.12 13:47 | ||
Оценка: |
Здравствуйте, niXman, Вы писали:
X>Здравствуйте, Abyx, Вы писали:
A>>
A>>[this]
A>>
X>т.е. захватывать мемберы нельзя? только this?
захватывать можно только переменные, а не поля объектов.
точно так же для `Foo* x;` нельзя написать `[&x->some]`
In Zen We Trust
Re[4]: lamdba и «error: capture of non-variable ‘type::v'»
|
От: |
niXman |
https://github.com/niXman |
Дата: | 17.07.12 13:49 | ||
Оценка: |
Здравствуйте, Abyx, Вы писали:
A>захватывать можно только переменные, а не поля объектов.
A>точно так же для `Foo* x;` нельзя написать `[&x->some]`
ясно.
зы
наговнокодил тыщи строк кода. да здравствует рефак!
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[3]: lamdba и «error: capture of non-variable ‘type::v'»
|
От: |
Abyx |
|
Дата: | 17.07.12 13:49 | ||
Оценка: |
Здравствуйте, niXman, Вы писали:
X>а this разве по умолчанию не захватывается?
нет.
посмотрите стандарт, там [this] отдельно описан в синтаксисе языка
In Zen We Trust
- Переместить
- Удалить
- Выделить ветку
Пока на собственное сообщение не было ответов, его можно удалить.
Created attachment 26999 [details]
the preprocessed file
~/gcc-test$ g++-4.7.0 -o test -v -save-temps ItemIncGroup.cpp
Using built-in specs.
COLLECT_GCC=g++-4.7.0
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/i686-pc-linux-gnu/4.7.0/lto-wrapper
Target: i686-pc-linux-gnu
Configured with: ../configure --program-suffix=-4.7.0
Thread model: posix
gcc version 4.7.0 (GCC)
COLLECT_GCC_OPTIONS='-o' 'test' '-v' '-save-temps' '-shared-libgcc' '-mtune=generic' '-march=pentiumpro'
/usr/local/libexec/gcc/i686-pc-linux-gnu/4.7.0/cc1plus -E -quiet -v -D_GNU_SOURCE ItemIncGroup.cpp -mtune=generic -march=pentiumpro -fpch-preprocess -o ItemIncGroup.ii
ignoring nonexistent directory "/usr/local/lib/gcc/i686-pc-linux-gnu/4.7.0/../../../../i686-pc-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/local/lib/gcc/i686-pc-linux-gnu/4.7.0/../../../../include/c++/4.7.0
/usr/local/lib/gcc/i686-pc-linux-gnu/4.7.0/../../../../include/c++/4.7.0/i686-pc-linux-gnu
/usr/local/lib/gcc/i686-pc-linux-gnu/4.7.0/../../../../include/c++/4.7.0/backward
/usr/local/lib/gcc/i686-pc-linux-gnu/4.7.0/include
/usr/local/include
/usr/local/lib/gcc/i686-pc-linux-gnu/4.7.0/include-fixed
/usr/include
End of search list.
COLLECT_GCC_OPTIONS='-o' 'test' '-v' '-save-temps' '-shared-libgcc' '-mtune=generic' '-march=pentiumpro'
/usr/local/libexec/gcc/i686-pc-linux-gnu/4.7.0/cc1plus -fpreprocessed ItemIncGroup.ii -quiet -dumpbase ItemIncGroup.cpp -mtune=generic -march=pentiumpro -auxbase ItemIncGroup -version -o ItemIncGroup.s
GNU C++ (GCC) version 4.7.0 (i686-pc-linux-gnu)
compiled by GNU C version 4.7.0, GMP version 4.3.2, MPFR version 2.4.2, MPC version 0.8.1
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
GNU C++ (GCC) version 4.7.0 (i686-pc-linux-gnu)
compiled by GNU C version 4.7.0, GMP version 4.3.2, MPFR version 2.4.2, MPC version 0.8.1
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: c256e2cdb5a4ae96bd7afc48ca236d31
ItemIncGroup.cpp: In member function ‘bool CItemIncGroup::SetIncrementalCountMax()’:
ItemIncGroup.cpp:7:38: error: capture of non-variable ‘CItemIncGroup::m_TotalIncrementalCount’
In file included from ItemIncGroup.cpp:3:0:
ItemIncGroup.h:17:18: note: ‘long int CItemIncGroup::m_TotalIncrementalCount’ declared here
Notes: Changing the type of m_pItemIncGroup from CItemInc to int will allow the code to compile. This code compiled with gcc 4.6.1.
It works if you remove the parentheses, which also makes the code valid C++ (currently it relies on a GNU extension that allows a variable array size for a parenthesised new expression, you get a warning with -pedantic or -Wvla) It seems that there's some interaction between the C++11 lambda parsing and the GNU extension
Hello, I have something similar in the OpenMM code (https://simtk.org/home/openmm), with no ()s following the "new" as in template <typename T> struct CUDAStream : public SoADeviceObject { unsigned int _length; unsigned int _subStreams; # line 68 unsigned int _stride; T** _pSysStream; T** _pDevStream; T* _pSysData; T* _pDevData; std::string _name; CUDAStream(int length, int subStreams = 1, std::string name=""); CUDAStream(unsigned int length, unsigned int subStreams = 1, std::string name=""); CUDAStream(unsigned int length, int subStreams = 1, std::string name=""); CUDAStream(int length, unsigned int subStreams = 1, std::string name=""); virtual ~CUDAStream(); void Allocate(); void Deallocate(); void Upload(); void Download(); void CopyFrom(const CUDAStream<T>& src); void Collapse(unsigned int newstreams = 1, unsigned int interleave = 1); T& operator[](int index); }; [...] template <typename T> void CUDAStream<T>::Allocate() { cudaError_t status; _pSysStream = new T*[_subStreams]; # line 125 _pDevStream = new T*[_subStreams]; _pSysData = new T[_subStreams * _stride]; status = cudaMalloc((void **) &_pDevData, _stride * _subStreams * sizeof(T)); RTERROR(status, (_name+": cudaMalloc in CUDAStream::Allocate failed").c_str()); for (unsigned int i = 0; i < _subStreams; i++) { _pSysStream[i] = _pSysData + i * _stride; _pDevStream[i] = _pDevData + i * _stride; } } for which 4.6.3 (Debian 4.6.3-5) happily crunches but 4.7 (Debian 4.7.0-9) gives me cd /homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/obj-x86_64-linux-gnu/platforms/cuda/sharedTarget && /usr/local/bin/c++ -DOpenMMCuda_EXPORTS -DOPENMM_LIBRARY_NAME=OpenMM -DOPENMM_MAJOR_VERSION=1 -DOPENMM_MINOR_VERSION=0 -DOPENMM_BUILD_VERSION=0 -DOPENMM_SVN_REVISION="exported" -DOPENMM_COPYRIGHT_YEARS="2008" -DOPENMM_AUTHORS="Peter.Eastman" -O3 -DNDEBUG -fPIC -I/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/platforms/cuda/src -I/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/platforms/cuda/./include -I/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/src -I/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/libraries/validate/include -I/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/platforms/reference/include -I/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/libraries/lbfgs/include -I/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/libraries/sfmt/include -I/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/libraries/lepton/include -I/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/libraries/quern/include -I/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/libraries/jama/include -I/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/olla/include -I/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/openmmapi/include -I/homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/./include -DOPENMMCUDA_BUILDING_SHARED_LIBRARY -o CMakeFiles/OpenMMCuda.dir/__/__/__/src/cuda/kApplyConstraints.cu_OpenMMCuda_generated.cpp.o -c /homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/obj-x86_64-linux-gnu/src/cuda/kApplyConstraints.cu_OpenMMCuda_generated.cpp /homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/platforms/cuda/./src/kernels//cudatypes.h: In member function ‘virtual void CUDAStream<T>::Allocate()’: /homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/platforms/cuda/./src/kernels//cudatypes.h:125:27: error: capture of non-variable ‘CUDAStream<T>::_subStreams’ /homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/platforms/cuda/./src/kernels//cudatypes.h:68:10: note: ‘unsigned int CUDAStream<T>::_subStreams’ declared here /homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/platforms/cuda/./src/kernels//cudatypes.h:126:27: error: capture of non-variable ‘CUDAStream<T>::_subStreams’ /homeLvm/moeller/alioth/debichem/experimental/openmm-4.1/platforms/cuda/./src/kernels//cudatypes.h:68:10: note: ‘unsigned int CUDAStream<T>::_subStreams’ declared here make[3]: *** [platforms/cuda/sharedTarget/CMakeFiles/OpenMMCuda.dir/__/__/__/src/cuda/kApplyConstraints.cu_OpenMMCuda_generated.cpp.o] Error 1 Thanks and regards, Steffen
N.B. I've changed the Summary, the "non-variable" in the diagnostic refers to a non-automatic variable, in this case a data member, which isn't allowed in a lamdba capture. The problem is not that the error says a member variable is a non-variable, it's that a new-expression is mistaken for a lambda-expresion.
(In reply to comment #2)
> Hello, I have something similar in the OpenMM code
> (https://simtk.org/home/openmm), with no ()s following the "new" as in
Please provide a minimal, complete example, those snippets do not allow your report to be reproduced or confirmed. This seems to be equivalent but works fine:
template <typename T>
struct CUDAStream
{
unsigned int _subStreams;
T** _pSysStream;
void Allocate();
};
template <typename T>
void CUDAStream<T>::Allocate()
{
_pSysStream = new T*[_subStreams];
}
Hello, this took me a while. It seems like the problem is in (or in the interaction with) nvcc, the NVidia compiler. For that you program for the graphics card and the host processor at the same time. The .cu files indicate such files that are not meant to be seen by the regular compiler at a first sight. It then generates preprocessed files for gcc to digest. $ rm -f t.cu_OpenMMCuda_generated.cpp; /usr/bin/nvcc t.cu -cuda -o t.cu_OpenMMCuda_generated.cpp && g++ -c t.cu_OpenMMCuda_generated.cpp t.cu: In member function ‘void CUDAStream<T>::Allocate()’: t.cu:12:27: error: capture of non-variable ‘CUDAStream<T>::_subStreams’ t.cu:4:10: note: ‘unsigned int CUDAStream<T>::_subStreams’ declared here $ cat t.cu template <typename T> struct CUDAStream { unsigned int _subStreams; T** _pSysStream; void Allocate(); }; template <typename T> void CUDAStream<T>::Allocate() { _pSysStream = new T*[_subStreams]; } The NVCC-generated code now has the ()s again: # 9 "t.cu" template< class T> void # 10 "t.cu" CUDAStream< T> ::Allocate() # 11 "t.cu" { # 12 "t.cu" (_pSysStream) = (new (T *[_subStreams])); # 13 "t.cu" } 4.6 crunges it, 4.7 does not. Sounds like we should prepare an email to NVidia. Anybody with any direct contacts? Thanks Steffen
$ nvcc --version nvcc: NVIDIA (R) Cuda compiler driver Copyright (c) 2005-2012 NVIDIA Corporation Built on Thu_Apr__5_00:24:31_PDT_2012 Cuda compilation tools, release 4.2, V0.2.1221 as shipping with Debian unstable in package version 4.2.9-1.
Anything to do with the cuda compiler is irrelevant here, this report is for a GCC bug not for other programs, even if they generate code that triggers the bug. Anyway, I'm confirming this, here's a reduced testcase that produces a slightly different eror, due to using a global instead of a data member: struct A { }; extern int n; void f() { A** p = new (A*[n]); } Accepted by 4.6 and earlier, rejected by 4.7 and later $ g++-4.7 -c t.cc t.cc: In function 'void f()': t.cc:7:21: warning: capture of variable 'n' with non-automatic storage duration [enabled by default] t.cc:3:5: note: 'int n' declared here N.B. 4.5 says t.cc: In function ‘void f()’: t.cc:7:19: warning: lambda expressions only available with -std=c++0x or -std=gnu++0x But that was fixed for 4.6
(In reply to comment #6)
> N.B. 4.5 says
>
> t.cc: In function ‘void f()’:
> t.cc:7:19: warning: lambda expressions only available with -std=c++0x or
> -std=gnu++0x
>
> But that was fixed for 4.6
I tested 4.5.2, that should be fixed in 4.5.3, see Bug 46159 and its dup Bug 47651
Author: jason Date: Fri Jun 1 21:19:22 2012 New Revision: 188127 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=188127 Log: PR c++/52725 * parser.c (cp_parser_binary_expression): Bail early if we're parsing tentatively and the LHS has a parse error. Added: trunk/gcc/testsuite/g++.dg/parse/new6.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/parser.c trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/g++.dg/template/sizeof-template-argument.C
Author: jason Date: Fri Jun 1 21:19:36 2012 New Revision: 188128 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=188128 Log: PR c++/52725 * parser.c (cp_parser_binary_expression): Bail early if we're parsing tentatively and the LHS has a parse error. Added: branches/gcc-4_7-branch/gcc/testsuite/g++.dg/parse/new6.C Modified: branches/gcc-4_7-branch/gcc/cp/ChangeLog branches/gcc-4_7-branch/gcc/cp/parser.c branches/gcc-4_7-branch/gcc/testsuite/ChangeLog branches/gcc-4_7-branch/gcc/testsuite/g++.dg/template/sizeof-template-argument.C
Fixed for 4.7.1. |
- Forum
- Beginners
- lazy initialisation with shared pointer
lazy initialisation with shared pointer
Hi
I am trying to introduce a lazy initialisation using a shared pointer.
The function that performs the initialisation is a public member function and uses a lambda.
I am unsure if the lambda is correct though. A compile error is generated on the code.
A small subset of the code looks something like this:
|
|
The compile error is:
|
|
Could anybody suggest where the code needs modification ?
Last edited on
std::call_once(once_flag, [/*sharep*/ & sptr](){ if(!sptr) sptr.reset(new Member); } ) ; //missing semicolon
http://en.cppreference.com/w/cpp/language/lambda (see lambda capture)
But then on line 40 you do
sptr->init(sptr, "Harry Potter", 12); //dereference the pointer
sptr is a null pointer at that time. don’t derefence null pointers.
Hi ne555
Thanks for the reply.
No compile error appears now, but
a runtime «segmentation fault» occurs instead, with the modified code:
|
|
Again,
sptr->init(sptr, "Harry Potter", 12);
Will cause UB because sptr
is empty.
Last edited on
|
|
Last edited on
Hi blongho,
many thanks. I’m only a beginner C++ coder, but slowly making my way through C++ Concurrency in Action by Anthony Williams.
The above code is simply a test case I’ve created in order to try out some of his discussion on pages 60-63.
one small change,
I modified line 36, from this:
sharep sptr(new Member());
to this:
sharep sptr = std::make_shared<Member>();
so no lazy initialization then.
Topic archived. No new replies allowed.