VS 2017 crashes when compiling template implementation - c++11

To make it short visual studio 2017 crashes when I am compiling this file:
#pragma once
/// #file
/// #brief Class mbe::HandleBase
#include <unordered_map>
//#include <cassert>
namespace mbe
{
template <class Derived>
class HandleBased abstract
{
public:
typedef unsigned long long int HandleID;
public:
HandleBased();
~HandleBased();
// Maybe rename to GetHandleId()?
HandleID ThisHandleId();
/*{
return id;
}*/
// Maybe rename to FindHandledObject
static Derived * FindPtr(HandleID id)
{
auto it = HandleBased::GetMap().find(id);
if (it == HandleBased::GetMap().end())
return nullptr;
// Should always be save
//assert(dynamic_cast<Derived *>(it->second));
return static_cast<Derived *>(it->second);
}
private:
static HandleID NextHandle()
{
// Every handle will get its own unique id
static HandleID next = 0;
return next++;
}
static std::unordered_map<HandleID, HandleBased *>& GetMap()
{
// Create the static map which will be used to keep track of the Derived handles and their ids
static std::unordered_map<HandleID, HandleBased *> map;
return map;
}
private:
HandleID id; // The id of this handle object
};
#pragma region Template Implementation
template<class Derived>
HandleBased<Derived>::HandleBased() :
id(NextHandle())
{
HandleBased::GetMap()[id] = this;
}
template<class Derived>
HandleBased<Derived>::~HandleBased()
{
auto it = HandleBased::GetMap().find(id);
HandleBased::GetMap().erase(it);
}
template<class Derived>
inline HandleID HandleBased<Derived>::ThisHandleId()
{
return id;
}
#pragma endregion
} // namespace mbe
It compiles fine when the ThisHandleId() function is defined directly below its definition. Is something wrong with my template implementation? I have noticed that the HandleID typedef does not show up in intellisense.
Sometimes VS crashes completely (goes grey and windows displays the message: "Visual Studio 2017 stopped working". Sometimes it just shows that ingame message: "C/C++ optimising compiler stopped working"
Furthermore, I get a ton of compile errors when defining the other functions beneath the HandleBase class or in an inline file. As I said, everything compiles just fine if all functions are implemented just beneath their definition. I have also experimented with removing inline which avoids the crash but gives me even more compile errors. Mosty complete non-sense such as:
2>c:\users\adrian\documents\visual studio 2017\projects\mars base engine ecs 5\mars base engine ecs\handlebase.h(75): warning C4346: "ThisHandleId": Abhängiger Name ist kein Typ
2>c:\users\adrian\documents\visual studio 2017\projects\mars base engine ecs 5\mars base engine ecs\handlebase.h(76): note: Präfix mit "typename" zum Angeben eines Typs
2>c:\users\adrian\documents\visual studio 2017\projects\mars base engine ecs 5\mars base engine ecs\handlebase.h(76): error C2988: Unerkannte Vorlagendeklaration/-definition
2>c:\users\adrian\documents\visual studio 2017\projects\mars base engine ecs 5\mars base engine ecs\handlebase.h(76): error C2059: Syntaxfehler: ""
2>c:\users\adrian\documents\visual studio 2017\projects\mars base engine ecs 5\mars base engine ecs\handlebase.h(76): error C2143: Syntaxfehler: Es fehlt ";" vor "{"
2>c:\users\adrian\documents\visual studio 2017\projects\mars base engine ecs 5\mars base engine ecs\handlebase.h(76): error C2447: "{": Funktionsheader fehlt - Parameterliste im alten Stil?
Sorry for the German comments, but u can probably guess what some of them meen. There is stuff like 'depended name is not a type', 'syntax error ""' and 'missing an ; before {'
Also, I don't think removing the inline is a good idea in the first place.
In case you are wondering what the code is for, its described in the acceted answer of this stack overflow question: Using shared_ptr for unique ownership (kind of) - is this good practice?
Hope you can help me with this weird occurence....
Thanks,
Adrian

HandleID is a scoped type. Hence, you will need to use HandleBased<Derived>::HandleID. Furthermore, since HandleID is a dependent type. Hence, you will need to use typename HandleBased<Derived>::HandleID.
Use:
template<class Derived>
inline typename HandleBased<Derived>::HandleID HandleBased<Derived>::ThisHandleId()
{
return id;
}
Alternatively, use trailing return type (Thanks are due to #Angew):
template <class Derived>
auto HandleBase<Derived>::ThisHandleId() -> HandleId
{
return id;
}
That works since trailing return types are within the scope of the class.

Related

where should I put the specialized std::hash for user defined type

I searched many pages, and I think I have known how to write the std::hash. But I don't know where to put it.
An example is presented here http://en.cppreference.com/w/cpp/utility/hash .
However, I defined my type Instance in namespace ca in file instance_management.h. I want to use unordered_set<Instance> in the same file in another class InstanceManager. So I write the following code:
namespace std
{
template <> struct hash<ca::Instance>
{
size_t operator()(const ca::Instance & instance) const
{
std::size_t seed = 0;
// Some hash value calculation here.
return seed;
}
};
} // namespace std
But where should I put it? I tried many locations but all failed.
I am using visual studio 2013. I tried to put the previous code in some locations but all failed to compile it.
// location 1
namespace ca
{
class Instance {...}
class InstanceManager
{
// ... some other things.
private unordered_set<Instance>;
}
}
// location 2
There are several ways.
Specializing std::hash
In your code make sure that your std::hash<Instance> specialization is preceded immediately by the Instance class definition, and followed by the use of the unordered_set container that uses it.
namespace ca
{
class Instance {...};
}
namespaces std {
template<> hash<Instance> { ... };
}
namespace ca {
class InstanceManager
{
// ... some other things.
private unordered_set<Instance>;
}
}
One drawback is that you can have funny name lookup interference when passing a std::hash<ca::Instance> to other functions. The reason is that the associated namespace (ca) of all the template arguments of std::hash can be used during name lookup (ADL). Such errors are a bit rare, but if they occur they can be hard to debug.
See this Q&A for more details.
Passing your hash to unordered_set
struct MyInstanceHash { ... };
using MyUnorderedSet = std:unordered_set<Instance, MyInstanceHash>;
Here, you simply pass your own hash function to the container and be done with it. The drawback is that you have to explicitly type your own container.
Using hash_append
Note, however, there is the N3980 Standard proposal is currently pending for review. This proposal features a much superior design that uses a universal hash function that takes an arbitrary byte stream to be hashed by its template parameter (the actual hashing algorithm)
template <class HashAlgorithm>
struct uhash
{
using result_type = typename HashAlgorithm::result_type;
template <class T>
result_type
operator()(T const& t) const noexcept
{
HashAlgorithm h;
using std::hash_append;
hash_append(h, t);
return static_cast<result_type>(h);
}
};
A user-defined class X then has to provide the proper hash_append through which it presents itself as a byte stream, ready to be hashed by the univeral hasher.
class X
{
std::tuple<short, unsigned char, unsigned char> date_;
std::vector<std::pair<int, int>> data_;
public:
// ...
friend bool operator==(X const& x, X const& y)
{
return std::tie(x.date_, x.data_) == std::tie(y.date_, y.data_);
}
// Hook into the system like this
template <class HashAlgorithm>
friend void hash_append(HashAlgorithm& h, X const& x) noexcept
{
using std::hash_append;
hash_append(h, x.date_);
hash_append(h, x.data_);
}
}
For more details, see the presentation by the author #HowardHinnant at CppCon14 (slides, video). Full source code by both the author and Bloomberg is available.
Do not specialise std::hash, instead write your own hash function object (see Edge_Hash below) and declare your unordered_set with two template arguments.
#include <unordered_set>
#include <functional>
namespace foo
{
// an edge is a link between two nodes
struct Edge
{
size_t src, dst;
};
// this is an example of symmetric hash (suitable for undirected graphs)
struct Edge_Hash
{
inline size_t operator() ( const Edge& e ) const
{
static std::hash<size_t> H;
return H(e.src) ^ H(e.dst);
}
};
// this keeps all edges in a set based on their hash value
struct Edge_Set
{
// I think this is what you're trying to do?
std::unordered_set<Edge,Edge_Hash> edges;
};
}
int main()
{
foo::Edge_Set e;
}
Related posts are, eg:
Inserting in unordered_set using custom hash function
Trouble creating custom hash function unordered_map
Thanks to everyone.
I have found the reason and solved the problem somehow: visual studio accepted the InstanceHash when I was defining instances_. Since I was changing the use of set to unordered_set, I forgot to specify InstanceHash when I tried to get the const_iterator, so this time the compiler tried to use the std::hash<> things and failed. But the compiler didn't locate the line using const_iterator, so I mistakenly thought it didn't accept InstanceHash when I was defining instances_.
I also tried to specialize the std::hash<> for class Instance. However, this specialization requires at least the declaration of class ca::Instance and some of its member functions to calculate the hash value. After this specialization, the definition of class ca::InstanceManage will use it.
I now generally put declarations and implementations of almost every classes and member functions together. So, the thing I need to do is probably to split the ca namespace scope to 2 parts and put the std{ template <> struct hash<ca::Instance>{...}} in the middle.

Parameter pack expansion fails

Consider the following simplified C++ code:
template <typename ... TEventArgs>
struct Event
{
// ...
};
template <typename T>
struct Parameter
{
using Type = T;
// ...
};
template <typename ... Parameters>
struct Command
{
Event<typename Parameters::Type...> Invoked;
};
int main()
{
Command<Parameter<int>, Parameter<float>> c;
}
The Visual Studio C++ compiler (November 2013 CTP, Visual Studio 2013 Update 1) produces the following error:
source.cpp(17): error C3546: '...' : there are no parameter packs available to expand
Mingw 4.8.1. on the other hand compiles the code without any problems. Apparently, the Visual Studio compiler has a bug that prevents it from expanding the parameter pack when the expression involves accessing a type of the variadic parameters. Other expansions work, though. For instance, Event<std::vector<Parameters>...> Invoked; compiles successfully or you could even successfully access static members to call a variadic function like this in Command's constructor: SomeVariadicFunc(Parameters::SomeStaticFunc()...);.
So, the questions are:
1) Which compiler is wrong: Visual Studio or mingw? Although I don't see anything that would prevent the typename Parameters::Type parameter pack expansion from working, I'm not 100% sure it's valid C++.
2) Is there a work around? Basically, I would have to perform a projection from a "sequence" of Parameters to a "sequence" of Parameters::Type. Is that possible? I tried to construct that list using a recursive struct but I could only come up with something like myStruct<type1, mystruct<type2, mystruct<type3, ...>>>, which is not what I need.
Thank you for your help.
Yakk was able to come up with a workaround for the problem in the comments above. The final version that compiles perfectly with both Visual Studio an mingw is the following:
template <typename ... TEventArgs>
struct Event
{
// ...
};
template <typename T>
struct Parameter
{
using Type = T;
// ...
};
template <typename ... Parameters>
struct Command
{
private:
// Workaround for the Visual Studio bug
template<typename T> struct ExpandArgs
{
typedef typename T::Type Type;
};
public:
Event<typename ExpandArgs<Parameters>::Type...> Invoked;
};
int main()
{
Command<Parameter<int>, Parameter<float>> c;
}

Using Concurrency::concurrent_queue together with std::unique_ptr

I want to use the Concurrency library of Visual Studio 2010 to pass actions between threads.
I have my class SimpleAction and pointers to it are stored in the Concurrency::concurrent_queue.
Using this definition, and 'consumption' logic it works:
typedef Concurrency::concurrent_queue<SimpleAction *> ActionQueue;
while (true)
{
SimpleAction *action = nullptr;
while (m_queue.try_pop(action))
{
action->process();
delete action;
}
Sleep(100);
}
However, when I change this to an std::unique_ptr, like this:
typedef Concurrency::concurrent_queue<std::unique_ptr<SimpleAction>> ActionQueue;
while (true)
{
std::unique_ptr<SimpleAction> action;
while (m_queue.try_pop(action))
{
action->process();
}
Sleep(100);
}
The compiler gives the following error message:
F:\DevStudio\Vs2010\VC\INCLUDE\concurrent_queue.h(366) : error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>'
with
[
_Ty=`anonymous-namespace'::SimpleAction
]
F:\DevStudio\Vs2010\VC\INCLUDE\memory(2347) : see declaration of 'std::unique_ptr<_Ty>::unique_ptr'
with
[
_Ty=`anonymous-namespace'::SimpleAction
]
F:\DevStudio\Vs2010\VC\INCLUDE\concurrent_queue.h(365) : while compiling class template member function 'void Concurrency::concurrent_queue<_Ty>::_Copy_item(Concurrency::details::_Concurrent_queue_base_v4::_Page &,size_t,const void *)'
with
[
_Ty=std::unique_ptr<`anonymous-namespace'::SimpleAction>
]
test.cpp(138) : see reference to class template instantiation 'Concurrency::concurrent_queue<_Ty>' being compiled
with
[
_Ty=std::unique_ptr<`anonymous-namespace'::SimpleAction>
]
It seems the compiler does not like this construction in concurrent_queue:
/*override*/ virtual void _Copy_item( _Page& _Dst, size_t _Index, const void* _Src )
{
new( &_Get_ref(_Dst,_Index) ) _Ty(*static_cast<const _Ty*>(_Src));
}
Which seems logical (we don't want an std::unique_ptr to be copied (it must be moved instead).
Questions:
Is this a known problem/limitation/feature of the Concurrency/PPL library of Visual Studio 2010?
Is this problem solved in Visual Studio 2012?
Or am I doing something wrong?
thanks,
Patrick

Error "C3145" and "C2061" in C++ Visual Studio

EDIT: What is C++/CLI? I am programming in Visual studio, and as far as I know using C++... Also, The first error was solved by Peter's comment, but I am still stuck on the second.
I am brand new to the world of C++, and have previously done all my work in Java. I am unfamiliar with the use of pointers and garbage collection (though I believe I understand the concept) and I believe that may be the source of my problems. I am getting the following error messages:
1>Runner.cpp(6): error C3145: 'formOutOfTime' : global or static variable may not have managed type 'System::Windows::Forms::Form ^'
1> may not declare a global or static variable, or a member of a native type that refers to objects in the gc heap
1>Runner.cpp(22): error C2061: syntax error : identifier 'FormOutOfTime'
My code is like this:
PurpleHealth.cpp (This is the file I believe the system calls to start it all off):
#include "FormOutOfTime.h"
#include "FormParentalOverride.h"
#include "Runner.h"
using namespace PurpleHealth;
[STAThreadAttribute]
int main(array<System::String ^> ^args)
{
// Enabling Windows XP visual effects before any controls are created
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
// Create the main window and run it
//Application::Run(gcnew FormOutOfTime());
Runner* runner = new Runner();
//delete runner;
return 0;
}
Runner.h (this is the header file I want to run all my main code, and launch the forms. I also struggle with the purpose behind the header files)
#include "stdafx.h"
#include "FormOutOfTime.h"
#include "FormParentalOverride.h"
class Runner
{
public:
Runner();
~Runner();
// functions
private:
void Go();
// member variables
};
And Finally Runner.cpp:
#include "stdafx.h"
#include "Runner.h"
#include "FormOutOfTime.h"
#include "FormParentalOverride.h"
//Variable Dclaration
System::Windows::Forms::Form^ formOutOfTime;//Error Here***************************
Runner::Runner()
{
// Do stuff if you need to
this->Go();
}
Runner::~Runner()
{
// Clear memory if you need to
}
void Runner::Go()
{
formOutOfTime = gcnew FormOutOfTime();//Error Here***************************
formOutOfTime->ShowDialog();
}
Please help me solve these messages, and even critique on form is appreciated. Thanks.
managed pointers cannot be declared at static or global scope. They can only be declared at function scope. Move the declaration of formOutOfTime from the top of the runner.cpp file to within the Go method

VC++ 2010 template typedef typename error

I am trying to migrate a project to VC++ 2010
The project contains the file TabbedMDI.h (by Danial Bowen) which gives the error "named followd by '::' must be a class or namespace name for the line
"typedef typename TClient::TTabCtrl TTabCtrl;"
code snipit follows
template <
class T,
class TClient = CTabbedMDIClient< CDotNetTabCtrl<CTabViewTabItem> >,
class TBase = WTL::CMDIWindow,
class TWinTraits = ATL::CFrameWinTraits>
class ATL_NO_VTABLE CTabbedMDIFrameWindowImpl :
public WTL::CMDIFrameWindowImpl<T, TBase, TWinTraits >
{
public:
// Expose the type of MDI client
typedef typename TClient TClient;
// Expose the type of tab control
typedef typename TClient::TTabCtrl TTabCtrl;
// Member variables
protected:
TClient m_tabbedClient;
Just compiled Daniel's SimpleTabbedMDIDemo sample from Custom Tab Controls, Tabbed Frame and Tabbed MDI with VC2010 Express (WTL 8.1, ATL 8.00 from WinDDK) without problem (except manifest duplication).
Your problem is elsewhere.
[Edit]
Do you use the latest TabbedMDI.h? mine has:
// History (Date/Author/Description):
// ----------------------------------
//
// 2005/07/13: Daniel Bowen
// - Namespace qualify the use of more ATL and WTL classes.
// - CTabbedMDIFrameWindowImpl:
// * Add GetMDITabCtrl

Resources