I want to store three arbitrary ints inside a std::vector without defining a struct/class. So I went for std::tuple<>:
std::vector<std::tuple<unsigned int, unsigned int, unsigned int>
Using MS VS 2013, it leads to the following error:
>c:\program files (x86)\microsoft visual studio 12.0\vc\include\vector(1628): error C2036: 'std::tuple<unsigned int,unsigned int,unsigned int> *' : unknown size
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\vector(1622) : while compiling class template member function 'void std::vector<std::tuple<unsigned int,unsigned int,unsigned int>,std::allocator<_Ty>>::_Tidy(void)'
1> with
1> [
1> _Ty=std::tuple<unsigned int,unsigned int,unsigned int>
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\vector(945) : see reference to function template instantiation 'void std::vector<std::tuple<unsigned int,unsigned int,unsigned int>,std::allocator<_Ty>>::_Tidy(void)' being compiled
1> with
1> [
1> _Ty=std::tuple<unsigned int,unsigned int,unsigned int>
1> ]
1> d:\projects\gl33\src\nvf.cpp(39) : see reference to class template instantiation 'std::vector<std::tuple<unsigned int,unsigned int,unsigned int>,std::allocator<_Ty>>' being compiled
1> with
1> [
1> _Ty=std::tuple<unsigned int,unsigned int,unsigned int>
1> ]
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped =======
Is this due to limitations in the MSVS2013 compiler? Or am I doing something wrong?
A class type is known (its name is known) but its size is unknown if the type has only been forward-declared, but not defined. E.g.
struct X;
sizeof(X) // error: X is incomplete
The size of a type is important for pointer arithmetic, which is another hint when looking at the compiler error (which mentions a pointer to tuple).
MSDN provides the following example for C2036:
struct A* pA;
int main() {
pA++; // C2036, size of A not known
((char*&)pA)++; // OK, if sizeof(A) == sizeof(char)
}
Where the struct A* pa implicitly forward-declares struct A.
Such a situation can happen with headers of the Standard Library when you don't include all required headers yourself. There are interdependencies between the types in the Standard Library. If a Standard Library header requires only a forward-declaration of tuple, it won't include the heavyweight tuple header itself in an effort to reduce compilation times.
I could reproduce the issue in the OP by including only <vector> but not <tuple>. Solution: manually include all headers you need types from - when using vector<tuple<..>>, include <tuple> (as well as <vector>). In general, including a header guarantees the availability of a certain set of types. To maximize portability, always make sure the headers you've included guarantee that you can use all the types in your program(*).
(*) More specifically, you should make sure that you have a definition for all types your program needs a definition for. Standard Library containers require their value types to be complete (at least at the point where the class template is instantiated). Hence, if your program requires a definition of vector<tuple<unsigned, unsigned>>, it also requires a definition of tuple<unsigned, unsigned>.
Related
We are getting strange unresolved symbols linking errors since we updated to Visual Studio 2015 update 3. Anyone else encountered the same kind of issues ?
What is really weird is that boost::get_pointer is a template method, defined in a boost header. I do not understand how we can get an undefined external symbol in that case :(.
Here is a reproducer, with boost 1.61 and Python 3.5.1:
#include <vector>
#include <boost/python.hpp>
using namespace boost::python;
class Canard {
public:
Canard() {}
virtual ~Canard() {}
};
BOOST_PYTHON_MODULE(coin)
{
register_ptr_to_python< std::shared_ptr<Canard> >();
}
And the error:
Severity Code Description Project File Line
Error LNK2019 unresolved external symbol "class Canard const volatile * __cdecl boost::get_pointer<class Canard const volatile >(class Canard const volatile *)" (??$get_pointer#$$CDVCanard###boost##YAPEDVCanard##PEDV1##Z) referenced in function "private: static struct _typeobject * __cdecl boost::python::objects::make_ptr_instance<class Canard,struct boost::python::objects::pointer_holder<class std::shared_ptr<class Canard>,class Canard> >::get_derived_class_object<class Canard>(struct boost::mpl::bool_<1>,class Canard const volatile *)" (??$get_derived_class_object#VCanard###?$make_ptr_instance#VCanard##U?$pointer_holder#V?$shared_ptr#VCanard###std##VCanard###objects#python#boost###objects#python#boost##CAPEAU_typeobject##U?$bool_#$00#mpl#3#PEDVCanard###Z) CCMasterKernelPyPy C:\work\dev\builds\internal\Master\SDK\MasterKernelPyPy\main.obj 1
But as soon as I remove the virtual in front of the destructor of the Canard class, then it starts working.... Does anyone have a clue ? Is it a Visual Studio bug ?
Visual Studio 2015 update 3 has added lots of features and improvements (see the release notes https://www.visualstudio.com/news/releasenotes/vs2015-update3-vs#visualcpp).
It also have some known issues (https://msdn.microsoft.com/vs-knownissues/vs2015-update3 see the Passing non-pointer-like types to uninitialized_copy section).
To fix your problem you need to explicitly specify the conversion to pointer of your class, explicitly:
namespace boost
{
template <>
Canard const volatile * get_pointer<class Canard const volatile >(
class Canard const volatile *c)
{
return c;
}
}
Good luck,
Ohad
In my Visual studio 2012 ,C++11 static function I have:
kuku* kuku::createKuku(bool enable, std::string dumpPat)
{
#ifndef ANDROID
#include "kukuWin.h"
return new kukuWin(enable, dumpPat);
#else
#include "kukuAndroid.h"
return new kukuAndroid(enable, dumpPat);
#endif
}
in c++98 it works , but here I have multiple errors:
1>C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\excpt.h(29): error : linkage specification is not allowed
1> extern "C" {
1> ^
1>
1>C:\Program Files (x86)\Windows Kits\8.0\Include\shared\windef.h(17): error : linkage specification is not allowed
1> extern "C" {
1> ^
1>
1>C:\Program Files (x86)\Windows Kits\8.0\Include\shared\specstrings.h(49): error : linkage specification is not allowed
1> extern "C" {
1> ^
1>
1>C:\Program Files (x86)\Windows Kits\8.0\Include\shared\driverspecs.h(133): error : linkage specification is not allowed
1> extern "C" {
1> ^
1>
1>C:\Program Files (x86)\Windows Kits\8.0\Include\shared\minwindef.h(42): error : linkage specification is not allowed
1> extern "C" {
1> ^
:)
Can anyone help me with it,
Thanks
An #include directive will put the full text of the included file exactly where the directive is. So all that stuff in "kukuWin.h" is going smack dab in the middle of your createKuku function, where it doesn't belong.
You'll almost always put inclusions at the top of your source files.
I've run into a problem driving me mad. I've implemented a timer using the followin timer entry construct:
typedef std::multimap<boost::posix_time::ptime, events::ITimeout*> TEntryMap;
TEntryMap entries_;
and I insert elements into the multimap with:
boost::posix_time::ptime tTimeout = boost::posix_time::microsec_clock::local_time() + boost::posix_time::milliseconds(timeout);
entries_.insert(std::make_pair(tTimeout, ptr)); // ptr is the events::ITimeout object
and in one translation unit (cpp file) it works perfectly. However, now I need to move this functionality to another cpp file, and now I get a compilation error:
1>Build started 2013-02-07 15:38:18.
1>ClCompile:
1> EventDispatcher.cpp
1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\utility(260): error C2678: binary '=' : no operator found which takes a left-hand operand of type 'const boost::posix_time::ptime' (or there is no acceptable conversion)
1> ....\boost\boost\date_time\posix_time\ptime.hpp(57): could be 'boost::posix_time::ptime &boost::posix_time::ptime::operator =(const boost::posix_time::ptime &)'
1> while trying to match the argument list '(const boost::posix_time::ptime, const boost::posix_time::ptime)'
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\utility(259) : while compiling class template member function 'std::pair<_Ty1,_Ty2> &std::pair<_Ty1,_Ty2>::operator =(std::pair<_Ty1,_Ty2> &&)'
1> with
1> [
1> _Ty1=const boost::posix_time::ptime,
1> _Ty2=events::ITimeout *
1> ]
1> ....\eventdispatcher.cpp(72) : see reference to class template instantiation 'std::pair<_Ty1,_Ty2>' being compiled
1> with
1> [
1> _Ty1=const boost::posix_time::ptime,
1> _Ty2=events::ITimeout *
1> ]
1>
I'm clueless and been struggling with this for 2 hours. I see no difference between the working implementation, and the non-working one. The same construct, same multimap, same includes, same everything! ;(
I found the cause of the problem, and it smells like a VS2010 C++ compiler bug (when using std::remove_if). In a function implementation later on in the class using the construct, I tried to remove elements in the map with:
void removeEntry(events::ITimeout* p)
{
std::remove_if(entries_.begin(), entries_.end(),
[&](TEntryMap::value_type& entry)->bool
{
return (entry.second == p);
}
);
}
Changing that code to:
void removeEntry(events::ITimeout* p)
{
TEntryMap::iterator it = std::find_if(entries_.begin(), entries_.end(),
[&](TEntryMap::value_type& entry)->bool
{
return (entry.second == p);
}
);
if (it != entries_.end()) entries_.erase(it);
}
makes the insertion code work. Go figure. Note that even if I use a struct based predicate instead of a lambda closure, it still doesn't work with std::remove_if...
I tried compiling the following code (From Ogre3d Beginner's Guide By Felix Kerger book)
#include "Ogre\ExampleApplication.h"
class Example1 : public ExampleApplication
{
public:
void createScene()
{Ogre::Entity* ent =
mSceneMgr->createEntity("MyEntity","Sinbad.mesh");
mSceneMgr->getRootSceneNode()->attachObject(ent);
}
};
int main (void)
{
Example1 app;
app.go();
return 0;
}
So the compiled Process didn't work. I am currently using Visual Studio 2010 and OgreSDK_vc10_v1-7-3.
The errors are
1>InitializeBuildStatus:
1> Touching "obj\Debug\OgreApp3.unsuccessfulbuild".
1>ClCompile:
1> main.cpp
1>d:\ogresdk_vc10_v1-7-3\include\ogre\exampleframelistener.h(343): warning C4244: '+=': conversion from 'double' to 'Ogre::Real', possible loss of data
1>d:\ogresdk_vc10_v1-7-3\include\ogre\exampleframelistener.h(344): warning C4244: '-=' : conversion from 'double' to 'Ogre::Real', possible loss of data
1>d:\ogresdk_vc10_v1-7-3\include\ogre\exampleframelistener.h(348): warning C4244: 'argument' : conversion from 'double' to 'Ogre::Real', possible loss of data
1>d:\ogresdk_vc10_v1-7-3\include\ogre\exampleframelistener.h(349): warning C4244: 'argument' : conversion from 'double' to 'Ogre::Real', possible loss of data
1>d:\ogresdk_vc10_v1-7-3\include\ogre\exampleframelistener.h(454): warning C4244: '-=' : conversion from 'double' to 'Ogre::Real', possible loss of data
1>ManifestResourceCompile:
1> All outputs are up-to-date.
1>MSVCRTD.lib(crtexew.obj) : error LNK2019: unresolved external symbol _WinMain#16 referenced in function ___tmainCRTStartup
1>bin\Debug\\OgreApp3.exe : fatal error LNK1120: 1 unresolved externals
1>
1>Build FAILED.
1>
1>Time Elapsed 00:00:10.57
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Replace the signature of your main function to the following:
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
right bottom on your project
->property linker->subsystem
change your subsystem with "CONSOLE(/SUBSYSTEM:CONSOLE)"
like this https://www.dropbox.com/s/li3qnzw152snizo/ogre.png
Your compiler thinks the program is a windows application but your source code is for a command line application.
This compiles fine in GCC 3 and 4. MSVC++ can't figure out the type of noFunction and throws some hideous errors. Note if you cast noFunction to BFunction, it works just fine in VS2010.
My question: is this a defect in VS2010, or GCC bending the rules?
#include <map>
using namespace std;
typedef bool (*AFunction)(int arg1, int arg2);
typedef bool (*BFunction)(long arg1, bool arg2);
bool noFunction(long, bool) { return true; }
void test(AFunction a)
{
make_pair(a, noFunction); //fails in VS2010
}
N.B. casting noFunction to BFunction fixes the problem in VS2010.
make_pair(a, (BFunction)noFunction); //works everywhere
.
.
.
Here is the error for reference:
1> makepairtest.cpp
1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\type_traits(197): error C2752: 'std::tr1::_Remove_reference<_Ty>' : more than one partial specialization matches the template argument list
1> with
1> [
1> _Ty=bool (__cdecl &)(long,bool)
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\xtr1common(356): could be 'std::tr1::_Remove_reference<_Ty&&>'
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\xtr1common(350): or 'std::tr1::_Remove_reference<_Ty&>'
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\type_traits(962) : see reference to class template instantiation 'std::tr1::remove_reference<_Ty>' being compiled
1> with
1> [
1> _Ty=bool (__cdecl &)(long,bool)
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\utility(26) : see reference to class template instantiation 'std::tr1::decay<_Ty>' being compiled
1> with
1> [
1> _Ty=bool (__cdecl &)(long,bool)
1> ]
1> c:\xxx\makepairtest.cpp(14) : see reference to class template instantiation 'std::tr1::_Unrefwrap<_Type>' being compiled
1> with
1> [
1> _Type=bool (__cdecl &)(long,bool)
1> ]
1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\type_traits(965): error C2528: 'abstract declarator' : pointer to reference is illegal
1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\type_traits(349): error C2528: 'type' : pointer to reference is illegal
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\type_traits(967) : see reference to class template instantiation 'std::tr1::add_pointer<_Ty>' being compiled
1> with
1> [
1> _Ty=bool (__cdecl &)(long,bool)
1> ]
1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\utility(148): error C2535: 'std::_Pair_base<_Ty1,_Ty2>::_Pair_base(const _Ty1 &,const _Ty2)' : member function already defined or declared
1> with
1> [
1> _Ty1=bool (__cdecl *)(int,int),
1> _Ty2=bool (__cdecl &)(long,bool)
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\utility(134) : see declaration of 'std::_Pair_base<_Ty1,_Ty2>::_Pair_base'
1> with
1> [
1> _Ty1=bool (__cdecl *)(int,int),
1> _Ty2=bool (__cdecl &)(long,bool)
1> ]
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\utility(174) : see reference to class template instantiation 'std::_Pair_base<_Ty1,_Ty2>' being compiled
1> with
1> [
1> _Ty1=bool (__cdecl *)(int,int),
1> _Ty2=bool (__cdecl &)(long,bool)
1> ]
1> c:\xxx\makepairtest.cpp(14) : see reference to class template instantiation 'std::pair<_Ty1,_Ty2>' being compiled
1> with
1> [
1> _Ty1=bool (__cdecl *)(int,int),
1> _Ty2=bool (__cdecl &)(long,bool)
1> ]
Taking the address of noFunction works with VC10 and gcc 4.5.2, i.e.:
make_pair(a, &noFunction);
Per the error message you posted, I would guess it has to do with how VC handles binding to rvalues.
"My question: is this a defect in VS2010, or GCC bending the rules?"
When in doubt blame Visual C++ and/or Bill Gates. Note that there is a difference between the value of noFunction when used in your code and the type defined by BFunction. noFunction will be a reference to a function whereas BFunction defines a pointer to a function. It is a bit hard to explain but it might help to contemplate the following program.
#include <iostream>
#include <typeinfo>
bool noFunction(long, bool) { return true; }
typedef bool (function_ref)(long, bool);
typedef bool (*function_ptr)(long, bool);
int
main()
{
std::cout << typeid(noFunction).name() << '\n';
std::cout << typeid(&noFunction).name() << '\n';
std::cout << typeid(function_ref).name() << '\n';
std::cout << typeid(function_ptr).name() << '\n';
return 0;
}
It seems that Visual C++ is choking on function references. I'm not sure if there is a legitimate reason why it would reject that but I would expect that you should be able to construct a pair with types that are a model of copy constructable. Eg you should be able construct but not assign std::pair<int, int const&>.