I'm working off of a sample c++ that I was given, and I'm trying to add threading to the program.
If anywhere in the program I add the following:
#include <thread>
void someFunction () {
std::thread t([]() {std::cout << "Hello" << std::endl; });
}
It fails to compile with the error:
1>C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\thread(48): error C3083: 'std': the symbol to the left of a '::' must be a type
1> C:\Users\Dennis Jeong\Documents\Stanford\CS148\cs148-raytracer\common\RayTracer.cpp(20): note: see reference to function template instantiation 'std::thread::thread<RayTracer::Run::<lambda_d2fd5ec539e104442fc3c5987873ac7f>,,void>(_Fn &&)' being compiled
1> with
1> [
1> _Fn=RayTracer::Run::<lambda_d2fd5ec539e104442fc3c5987873ac7f>
1> ]
However, if I create a new c++ project in visual studio, this works.
Where could the error possibly be?
If it is helpful, the cmake file is here:
https://gist.github.com/w0nche0l/aef2a112b596f489705441f429e725b5
EDIT: additionally, I'm sure that it is not the lambda syntax that is causing this error, because I can create and run lambdas without threads fine.
Related
This question already has answers here:
Why is this code trying to call the copy constructor?
(2 answers)
Closed 4 years ago.
It's taken me a while, but I've finally constructed a minimal example with illustrates the problem I'm having.
#include <memory>
#include <vector>
class Thing
{
};
class Box
{
public:
std::vector<std::unique_ptr<Thing>> Things;
static Box MakeBox() {Box b; return b;}
};
My real program is obviously quite a lot more complicated than this.
GCC 4.8.3 happily compiles this. It also compiles the real application, which works perfectly.
Visual Studio 2012 insists that this code is not correct, giving me error C2248 on line 606 of vc\include\xmemory0. If I wade through several miles of compiler output, I discover the real source of the error is line 11 in the above example. (The line that defines Things.) VS also refuses to compile my real application, with the same error.
So, is this code correct or not? If it's not correct, then why does GCC accept it? And how to I make it correct? If it is correct, then why won't VS compile it? Is there some way I can unconditionally force VS to actually compile my program?
Output from VS:
1>------ Build started: Project: TestUniquePtr, Configuration: Debug Win32 ------
1> Main.cpp
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\xmemory0(606): error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>'
1> with
1> [
1> _Ty=Thing
1> ]
1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\memory(1447) : see declaration of 'std::unique_ptr<_Ty>::unique_ptr'
1> with
1> [
1> _Ty=Thing
1> ]
1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\xmemory0(605) : while compiling class template member function 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)'
1> with
1> [
1> _Ty=std::unique_ptr<Thing>
1> ]
1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\xmemory0(751) : see reference to function template instantiation 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)' being compiled
1> with
1> [
1> _Ty=std::unique_ptr<Thing>
1> ]
1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\type_traits(743) : see reference to class template instantiation 'std::allocator<_Ty>' being compiled
1> with
1> [
1> _Ty=std::unique_ptr<Thing>
1> ]
1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\vector(655) : see reference to class template instantiation 'std::is_empty<_Ty>' being compiled
1> with
1> [
1> _Ty=std::allocator<std::unique_ptr<Thing>>
1> ]
1> d:\projects\c++\testuniqueptr\testuniqueptr\main.cpp(11) : see reference to class template instantiation 'std::vector<_Ty>' being compiled
1> with
1> [
1> _Ty=std::unique_ptr<Thing>
1> ]
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Your problem isn't std::unique_ptr but std::vector.
Your compiler comes with an old version of std::vector that requires the element type to be copyable.
The return by value (return b;) should invoke a move of the vector, but your std::vector doesn't implement move.
std::unique_ptr is moveable but not copyable, therefore it doesn't meet the pre-C++11 requirements for being used in std::vector... a requirement which still applies to VC++ 2012.
Your best option is to use a newer compiler and standard library. One that supports move semantics on std::vector.
Otherwise you might make some progress by eliminating the copy of std::vector, for example, by having MakeBox fill in an output argument rather than returning a new object.
static void MakeBox(Box& b) { /* fill Things in b provided by caller */ }
That's probably an exercise in futility though, because whenever the vector needs to grow, it has to relocate the existing elements to new storage, and with incomplete move support, it will try to copy those.
The problem is that Box has no move constructor, thus returning a Box requires it to have a copy constructor (which it can't because unique_ptr is not copyable). All you have to do is define a move constructor for Box:
Box::Box(Box&& other)
: Things(std::move(other.Things))
{
}
With more recent editions, the compiler will generate the move constructor for you.
The following code compiles just fine with VC 15.3.5:
#include <Windows.h>
#include <string>
#include <memory>
#include <optional>
#include <functional>
class TypeDictionary;
class IStructureField {};
using FieldFactory = std::function<std::unique_ptr<IStructureField>(TypeDictionary& dict, LPCSTR szName, std::optional<ULONG> ulOffset, std::optional<std::string> strFieldType, std::optional<ULONG> ulFieldSize)>;
int main()
{
FieldFactory ff;
ff = [](TypeDictionary& dict, LPCSTR szName, std::optional<ULONG> ulOffset, std::optional<std::string> szFieldType, std::optional<ULONG> ulFieldSize) -> std::unique_ptr<IStructureField> {
return std::unique_ptr<IStructureField>();
};
return 0;
}
It produces the following error message with 15.4.0:
1>f:\projects\fullpath\fullpath\fullpath.cpp(22): error C2679: binary '=': no operator found which takes a right-hand operand of type 'main::<lambda_36489dce1cc59e5a8de4329a29806b5a>' (or there is no acceptable conversion)
1>c:\program files (x86)\microsoft visual studio\2017\enterprise\vc\tools\msvc\14.11.25503\include\functional(656): note: could be 'std::function<std::unique_ptr<IStructureField,std::default_delete<_Ty>> (TypeDictionary &,LPCSTR,std::optional<ULONG>,std::optional<std::string>,std::optional<ULONG>)> &std::function<std::unique_ptr<_Ty,std::default_delete<_Ty>> (TypeDictionary &,LPCSTR,std::optional<ULONG>,std::optional<std::string>,std::optional<ULONG>)>::operator =(std::nullptr_t) noexcept'
1> with
1> [
1> _Ty=IStructureField
1> ]
1>c:\program files (x86)\microsoft visual studio\2017\enterprise\vc\tools\msvc\14.11.25503\include\functional(629): note: or 'std::function<std::unique_ptr<IStructureField,std::default_delete<_Ty>> (TypeDictionary &,LPCSTR,std::optional<ULONG>,std::optional<std::string>,std::optional<ULONG>)> &std::function<std::unique_ptr<_Ty,std::default_delete<_Ty>> (TypeDictionary &,LPCSTR,std::optional<ULONG>,std::optional<std::string>,std::optional<ULONG>)>::operator =(std::function<std::unique_ptr<_Ty,std::default_delete<_Ty>> (TypeDictionary &,LPCSTR,std::optional<ULONG>,std::optional<std::string>,std::optional<ULONG>)> &&)'
1> with
1> [
1> _Ty=IStructureField
1> ]
1>c:\program files (x86)\microsoft visual studio\2017\enterprise\vc\tools\msvc\14.11.25503\include\functional(612): note: or 'std::function<std::unique_ptr<IStructureField,std::default_delete<_Ty>> (TypeDictionary &,LPCSTR,std::optional<ULONG>,std::optional<std::string>,std::optional<ULONG>)> &std::function<std::unique_ptr<_Ty,std::default_delete<_Ty>> (TypeDictionary &,LPCSTR,std::optional<ULONG>,std::optional<std::string>,std::optional<ULONG>)>::operator =(const std::function<std::unique_ptr<_Ty,std::default_delete<_Ty>> (TypeDictionary &,LPCSTR,std::optional<ULONG>,std::optional<std::string>,std::optional<ULONG>)> &)'
1> with
1> [
1> _Ty=IStructureField
1> ]
1>f:\projects\fullpath\fullpath\fullpath.cpp(22): note: while trying to match the argument list '(FieldFactory, main::<lambda_36489dce1cc59e5a8de4329a29806b5a>)'
1>Done building project "FullPath.vcxproj" -- FAILED.
As I saw on cppcon (Stephan's talk), a lot of work has been done on <functional>... Could this be related? Any mistake I made?
Workarounds would be fine too.
Edit1: Added the two include files to help understand the issue is not there: Same error...
Edit2: After I repaired my VS installation, the code just compiled. However, the original code did not. I had bumped in https://developercommunity.visualstudio.com/content/problem/74313/compiler-error-in-xsmf-control-with-stdoptional-pa.html before and attempted the workaround (which exposed the issue I faced). Without the workaround, the code compiles (but hits the __this issue again...).
I'm very new to C++/VS and might missing something in the code/configuration of my project.
In my solution I have 2 projects:
first is NTL which I downloaded from https://bitbucket.org/ben_key/ntl, and compiled to a static library NTL.lib.
a 'test' project in which: (1) I added the header files by specifying their directory in the properties->C++->Additional Include Files, (2) in the properties->Linker->Input->Additional Dependencies I added "NTL.lib" (3)copied the NTL.lib file to be in the same directory as the main cpp file of the 'test' project.
My cpp only contains:
#include <NTL/GF2X.h>
int main() {
GF2X P;
return 1;
}
The build gives the output:
1>------ Build started: Project: test, Configuration: Release Win32 ------
1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V120\Microsoft.CppBuild.targets(388,5): warning MSB8028: The intermediate directory (Release\) contains files shared from another project (ntl-test.vcxproj). This can lead to incorrect clean and rebuild behavior.
1> QuickTest.cpp
1>..\tests\QuickTest.cpp(43): warning C4101: 'n' : unreferenced local variable
1>D:\studies\Thesis\NTL-Ben-Key\Include\NTL/vector.h(79): warning C4291: 'void *operator new(size_t,_ntl_vector_placement)' : no matching operator delete found; memory will not be freed if initialization throws an exception
1> D:\studies\Thesis\NTL-Ben-Key\Include\NTL/vector.h(36) : see declaration of 'operator new'
1> D:\studies\Thesis\NTL-Ben-Key\Include\NTL/vector.h(319) : see reference to function template instantiation 'void NTL::BlockConstruct<T>(T *,long)' being compiled
1> with
1> [
1> T=NTL::zz_p
1> ]
1> D:\studies\Thesis\NTL-Ben-Key\Include\NTL/vector.h(291) : while compiling class template member function 'void NTL::Vec<NTL::zz_p>::DoSetLength(long)'
1> D:\studies\Thesis\NTL-Ben-Key\Include\NTL/vector.h(115) : see reference to function template instantiation 'void NTL::Vec<NTL::zz_p>::DoSetLength(long)' being compiled
1> D:\studies\Thesis\NTL-Ben-Key\Include\NTL/vec_lzz_p.h(14) : see reference to class template instantiation 'NTL::Vec<NTL::zz_p>' being compiled
1> MyTest.cpp
1>MyTest.cpp(4): error C2065: 'GF2X' : undeclared identifier
1>MyTest.cpp(4): error C2146: syntax error : missing ';' before identifier 'P'
1>MyTest.cpp(4): error C2065: 'P' : undeclared identifier
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
It is really a simple thing and I didn't figured out what I'm missing.
From NTL/include/NTL/ tools.h:
#define NTL_NAMESPACE NTL
#define NTL_OPEN_NNS namespace NTL_NAMESPACE {
#define NTL_CLOSE_NNS }
So when the preprocessor encounters NTL_OPEN_NNS, as is the case in the include file GF2X.h, it expands it to namespace NTL meaning the GF2X class is declared insided the namespace NTL. In order to use it you need to fully qualify it as NTL::GF2X or use using namespace NTL for discussion about which one look here for example.
Likewise at the end of GF2X.h there is a closing bracket after expanding NTL_CLOSE_NNS
I'm using visual studio 2012 and I isolated a problem in my code to this, but I can't solve it. When running it in release mode it works perfect, but I get an error if I run it in debug.
The code is:
#include "stdafx.h"
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>
typedef boost::numeric::ublas::matrix<double> BMT;
BMT fun()
{
BMT mym;
mym.resize(3,3);
for(int i = 0; i<9;++i) mym(i/3,i%3)=i;
std::cout << mym << std::endl;
return mym;
}
int main(int argc, char* argv[])
{
fun();
//closing message
std::cout<<std::endl<<"press enter to exit."<<std::endl;
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
}
and the error in debug is the following:
1>------ Build started: Project: myproject, Configuration: Debug x64 ------
1> myapp.cpp
1>C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\xmemory(348): error C4996: 'std::_Uninitialized_copy0': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators'
1> C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\xmemory(333) : see declaration of 'std::_Uninitialized_copy0'
1> C:\thirdparty\vs2012\x64\boost_1_53_0\boost/numeric/ublas/storage.hpp(94) : see reference to function template instantiation '_FwdIt std::uninitialized_copy<const double*,double*>(_InIt,_InIt,_FwdIt)' being compiled
1> with
1> [
1> _FwdIt=double *,
1> _InIt=const double *
1> ]
1> C:\thirdparty\vs2012\x64\boost_1_53_0\boost/numeric/ublas/storage.hpp(89) : while compiling class template member function 'boost::numeric::ublas::unbounded_array<T>::unbounded_array(const boost::numeric::ublas::unbounded_array<T> &)'
1> with
1> [
1> T=double
1> ]
1> C:\thirdparty\vs2012\x64\boost_1_53_0\boost/numeric/ublas/matrix.hpp(160) : see reference to function template instantiation 'boost::numeric::ublas::unbounded_array<T>::unbounded_array(const boost::numeric::ublas::unbounded_array<T> &)' being compiled
1> with
1> [
1> T=double
1> ]
1> C:\thirdparty\vs2012\x64\boost_1_53_0\boost/numeric/ublas/matrix.hpp(100) : see reference to class template instantiation 'boost::numeric::ublas::unbounded_array<T>' being compiled
1> with
1> [
1> T=double
1> ]
1> junkApp1.cpp(10) : see reference to class template instantiation 'boost::numeric::ublas::matrix<T>' being compiled
1> with
1> [
1> T=double
1> ]
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Do you know what can the problem be?
I was having a similar issue using ublas.
I am not sure what the cause might be but I suppose it's got to do with ublas' copy on write / copy on demand optimizations. Would it be an option to just use the define -D_SCL_SECURE_NO_WARNINGS and be done with it? I have that set globally as I consider 90% of those warnings OS specifc BS anyway.
The problem is that you are compiling with warnings treated as errors.
EDIT: Microsoft has decided that certain parts of C++ (and C) are deprecated, and the compiler reports use of those parts as errors unless _SCL_SECURE_NO_WARNINGS (respectively _CRT_SECURE_NO_WARNINGS) is defined.
Edit:
This has been reported as a VS2012 C++ compiler bug on Microsoft Connect (link).
Nov. 11, 2014: Microsoft has responded saying the fix for this bug should show up in the next major release of Visual C++.
I've been struggling with a VS2012 compiler error message I don't understand, so I trimmed down the problem to what seems like the bare minimum.
I'm building the following main.cpp using VS2012:
#include <utility>
template <typename T>
struct A
{
T x;
A(A&& other) : x(std::move(other.x)) { }
A(T&& x) : x(std::move(x)) { }
};
template <typename T>
A<T> build(T&& x)
{
return A<T>(std::move(x));
}
int main(int argc, char* argv[])
{
auto f = []()
{
return build([](){}); //error here
};
return 0;
}
The salient point is that I'm trying to use a lambda as the template type T of the build function. The error message I get is:
1> main.cpp
1>C:\test\main.cpp(21): error C2664: 'A<T>::A(A<T> &&)' : cannot convert parameter 1 from 'A<T>' to 'A<T> &&'
1> with
1> [
1> T=void (__cdecl *)(void)
1> ]
1> and
1> [
1> T=main::<lambda_c3c618d445b3cb24eede9bf304860ad7>::()::<lambda_4240e93016e3e420ff8383c9350ae130>
1> ]
1> and
1> [
1> T=void (__cdecl *)(void)
1> ]
1> Reason: cannot convert from 'A<T>' to 'A<T>'
1> with
1> [
1> T=main::<lambda_c3c618d445b3cb24eede9bf304860ad7>::()::<lambda_4240e93016e3e420ff8383c9350ae130>
1> ]
1> and
1> [
1> T=void (__cdecl *)(void)
1> ]
1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
I've done my research and looked up the page for the error message (link), but I still can't figure out what the problem is. Could you please explain this compiler error?
edit
Something is definitely weird here. If I change the code in main to look like this:
auto f = []()
{
int* n = new int(0);
auto g = [=](){ return *n; };
*n++;
return build<decltype(g)>(std::move(g));
};
I get an error message suggesting that T=int (__cdecl *)(void) in the call to build - which would mean that decltype(g) is giving me a function pointer? Huh? I'm capturing a pointer by value and then modifying it afterwards - shouldn't it have to create a functor - and one that has no cast to function pointer? Maybe I'm not understanding something.
See related: Lambda expressions : n3290 draft
Also, if this is a bug in the VS2012 compiler, can you think of a workaround?
I can confirm that using GCC (on linux), this code compiles just fine.
So I'd say that VisualStudio seems to be the source of the error.
I don't have Windows or Visual Studio to verify, nor do I have much experience with lambda functions in C++, but perhaps you need to include the (albeit empty) parameter list in the function? i.e. change line 21 to
return build([](){});
Both versions compile with GCC, but perhaps Visual Studio is a bit more picky.
The other question I might have is whether the lambda function you're defining at line 24 will work out since its return value involves the lambda function you're defining inside the function itself.
I do not know if that behavior comply with the standard but with VC++ 2019 that error happen only with the option /permissive-, then when the strict mode is on.
Nevertheless here is how to solve the problem, by just casting the lambda with a reference type:
template <typename FUNC>
void f(FUNC& o){}
int main()
{
f((std::function<void()>&)[](){});
// or also:
auto func = [](){};
f(func);
}