I trying to fix pretty hard program to me I got from gamedev book. I think it's crashed because an author used Windows and I use Linux (g++). In short I have couple of classes to perform Application State's logic, and I have map of maps to hold states with its callbacks:
enum class StateType {
Intro = 1, MainMenu, Game, Paused, GameOver, Credits
};
using Bindings = std::unordered_map<std::string, Binding*>;
using CallbackContainer = std::unordered_map<std::string, std::function<void(EventDetails*)>>;
using Callbacks = std::unordered_map<StateType, CallbackContainer>;
class EventManager {
public:
...
template<class T>
bool AddCallback(StateType l_state, const std::string& l_name,
void(T::*l_func)(EventDetails*), T* l_instance) {
auto itr = m_callbacks.emplace(l_state, CallbackContainer()).first;
auto temp = std::bind(l_func, l_instance, std::placeholders::_1);
return itr->second.emplace(l_name, temp).second;
}
private:
Callbacks m_callbacks;
I'm not sure what parts of my code to include here. Anyway I get a terrible stack trace:
/usr/include/c++/5/bits/hashtable_policy.h: In instantiation of ‘struct std::__detail::__is_noexcept_hash<StateType, std::hash<StateType> >’:
/usr/include/c++/5/type_traits:137:12: required from ‘struct std::__and_<std::__is_fast_hash<std::hash<StateType> >, std::__detail::__is_noexcept_hash<StateType, std::hash<StateType> > >’
/usr/include/c++/5/type_traits:148:38: required from ‘struct std::__not_<std::__and_<std::__is_fast_hash<std::hash<StateType> >, std::__detail::__is_noexcept_hash<StateType, std::hash<StateType> > > >’
/usr/include/c++/5/bits/unordered_map.h:100:66: required from ‘class std::unordered_map<StateType, std::function<BaseState*()> >’
/home/xxx/Projects/mushrooom/BaseState.h:48:28: required from here
/usr/include/c++/5/bits/hashtable_policy.h:85:34: error: no match for call to ‘(const std::hash<StateType>) (const StateType&)’
noexcept(declval<const _Hash&>()(declval<const _Key&>()))>
...
/usr/include/c++/5/bits/unordered_map.h:649:7: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<StateType> >, std::__detail::__is_noexcept_hash<StateType, std::hash<StateType> > > >’
equal_range(const key_type& __x) const
...
/home/xxx/Projects/mushrooom/EventManager.h: In member function ‘bool EventManager::AddCallback(StateType, const string&, void (T::*)(EventDetails*), T*)’:
/home/xxx/Projects/mushrooom/EventManager.h:93:32: error: ‘using Callbacks = class std::unordered_map<StateType, std::unordered_map<std::basic_string<char>, std::function<void(EventDetails*)> > > {aka class std::unordered_map<StateType, std::unordered_map<std::basic_string<char>, std::function<void(EventDetails*)> > >}’ has no member named ‘emplace’
auto itr = m_callbacks.emplace(l_state, CallbackContainer()).first;
Seems like Callbacks has no member emplace, but it's std::unordered_map and it has such method.
g++-5, linux
It has nothing to do with emplace - it is the missing hash function!
You are using an std::unordered_map, which is in other words a hash map. If you want to use an object as a key, this object must provide a function by which a hash value can be calculated.
You now have two options:
provide a template specialisation of std::hash for your class or pass an own class as third (hasher) template parameter to std::unordered_map
use std::map instead - this is a tree-map not requiring a hash function.
Related
I have a queue that extends the std::queue
template<typename T, typename Container = std::queue<T>>
class device_queue : public std::queue<T, Container>
{
private:
flag::state state = flag::state::IDLE;
public:
void SetState(const flag::state& _state)
{
state = _state;
}
flag::state GetState() const
{
return state;
}
};
it being declared:
device_queue<Event> cpu_queue;
the usage is just using pop and front, but I keep getting the following error message
/usr/include/c++/9/bits/stl_queue.h: In instantiation of ‘void std::queue<_Tp, _Sequence>::push(const value_type&) [with _Tp = Event; _Sequence = std::queue<Event, std::deque<Event, std::allocator<Event> > >; std::queue<_Tp, _Sequence>::value_type = Event]’:
src/handler.cpp:11:31: required from here
/usr/include/c++/9/bits/stl_queue.h:260:11: error: ‘class std::queue<Event, std::deque<Event, std::allocator<Event> > >’ has no member named ‘push_back’
260 | { c.push_back(__x); }
| ~~^~~~~~~~~
/usr/include/c++/9/bits/stl_queue.h: In instantiation of ‘void std::queue<_Tp, _Sequence>::pop() [with _Tp = Event; _Sequence = std::queue<Event, std::deque<Event, std::allocator<Event> > >]’:
src/handler.cpp:92:23: required from here
/usr/include/c++/9/bits/stl_queue.h:295:4: error: ‘class std::queue<Event, std::deque<Event, std::allocator<Event> > >’ has no member named ‘pop_front’
295 | c.pop_front();
| ~~^~~~~~~~~
I am not sure where I am going wrong or how to fix this error. Any help would be greatly appreciated
You have a dependency from queue to queue when you make a queue the container type used in the queue and queue does not satisfy all the requirements in itself.
I suggest using a std::deque as the default container instead, like it is by default for a queue.
So instead of
template<typename T, typename Container = std::queue<T>>
make it
template<typename T, typename Container = std::deque<T>>
From cppreference:
"The type of the underlying container to use to store the elements. The container must satisfy the requirements of SequenceContainer. Additionally, it must provide the following functions with the usual semantics:"
back()
front()
push_back()
pop_front()
Background
I have been writing a StateMachine whose transition table is loaded at runtime. The action to take upon each transition is stored as a string. The string is converted to a std::function object that points to a member function of the state machine class. When an event occurs, and results in a transition, that function is invoked.
Problem
I have successfully used this strategy before to decide which function is called at run time. Unfortunately, I've been running into the following error:
error: return type 'XStMachine::TrFunc {aka class std::function<void (XStMachine::*)(const EventData&)>}' is incomplete
Or
invalid use of incomplete type
Steps Taken
I consulted Google and Stackoverflow. I got a number of ideas including taking the definition out of the place where the type is incomplete. Unfortunately, I couldn't get it to work successfully.
I tried using a raw pointer instead of a unique_ptr and found that things worked magically.
I ended up reading a little on the difference between how shared_ptr and unique_ptr handle incomplete types. I tried a shared_ptr, but that did not solve my issue either.
I tried creating a friend class to my state machine in the hope that by the time of the friend class' declaration, the type would be considered whole. I could not get this to work.
Finally, I created the following minimal example (Uncomment code to reproduce the error, please.) which demonstrates the problems I ran into: http://coliru.stacked-crooked.com/a/791092c7ca8fff24 and came to the experts! :)
Source Code
#include <iostream>
#include <string>
#include <functional>
#include <memory>
#include <map>
#include <iomanip>
using namespace std;
struct EventData
{
unsigned int x;
};
class Friendly; // Required for compiling the code. Why?
class XStMachine
{
friend class Friendly;
unique_ptr<Friendly> fPtr; //-- Doesn't compile if Friendly is not fwd. declared
unsigned int y;
unsigned int z;
public:
typedef void(XStMachine::*TrFuncPtr)(EventData const&);
typedef std::function<TrFuncPtr> TrFunc;
private:
// map<string, TrFunc> fMap; //-- Doesn't compile because TrFunc is incomplete
// unique_ptr<map<string, TrFunc>> fMap; // Doesn't compile; incomplete type.
map<string, TrFunc> *fMap; // Compiles with incomplete type.
protected:
void tranFunc1(EventData const &d)
{
y = d.x;
}
void tranFunc2(EventData const &d)
{
z = d.x;
}
public:
XStMachine()
{
// Code to init fMap
}
// The code below doesn't compile. incomplete type.
TrFunc getTranFunc(std::string const &s)
{
return (*fMap)[s];
}
~XStMachine()
{
}
};
class Friendly
{
// unique_ptr<map<string, XStMachine::TrFunc> fMap; // Doesn't compile, the type is incomplete.
public:
Friendly()
{
// Code to allocate and init fMap
}
// Dosen't compile if defined here because the return type is incomplete.
//XStMachine::TrFunc& getTranFunc(std::string const&)
//{
// return (*fMap)[s];
//}
};
// The type is incomplete -> Will this work inside a separate cpp file?
//XStMachine::TrFunc& getTranFunc(std::string const &s)
//{
// Weird - Can't access protected members though we're friends. :/
/*
static map<string, XStMachine::TrFunc> fMap = {{"tranFunc1", function(&XStMachine::tranFunc1)},
{"tranFunc2", function(&XStMachine::tranFunc2)}
};
*/
//return fMap[s];
//}
int main() {
cout << "I need to understand incomplete types." << endl;
return 0;
}
Full Error Output from Coliru (gcc 6.3, C++ 14)
main.cpp: In member function 'XStMachine::TrFunc XStMachine::getTranFunc(const string&)':
main.cpp:48:3: error: return type 'XStMachine::TrFunc {aka class std::function<void (XStMachine::*)(const EventData&)>}' is incomplete
{
^
In file included from /usr/local/include/c++/6.3.0/bits/stl_algobase.h:64:0,
from /usr/local/include/c++/6.3.0/bits/char_traits.h:39,
from /usr/local/include/c++/6.3.0/ios:40,
from /usr/local/include/c++/6.3.0/ostream:38,
from /usr/local/include/c++/6.3.0/iostream:39,
from main.cpp:1:
/usr/local/include/c++/6.3.0/bits/stl_pair.h: In instantiation of 'struct std::pair<const std::__cxx11::basic_string<char>, std::function<void (XStMachine::*)(const EventData&)> >':
/usr/local/include/c++/6.3.0/bits/stl_map.h:481:10: required from 'std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = std::__cxx11::basic_string<char>; _Tp = std::function<void (XStMachine::*)(const EventData&)>; _Compare = std::less<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, std::function<void (XStMachine::*)(const EventData&)> > >; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = std::function<void (XStMachine::*)(const EventData&)>; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = std::__cxx11::basic_string<char>]'
main.cpp:49:23: required from here
/usr/local/include/c++/6.3.0/bits/stl_pair.h:196:11: error: 'std::pair<_T1, _T2>::second' has incomplete type
_T2 second; /// #c second is a copy of the second object
^~~~~~
In file included from main.cpp:3:0:
/usr/local/include/c++/6.3.0/functional:1526:11: note: declaration of 'class std::function<void (XStMachine::*)(const EventData&)>'
class function;
^~~~~~~~
Objectives
Primary: Understand what is going on in the example code and fix it.
Secondary: Gain a clear understanding of what an incomplete type is so that I can:
* Solve related problems in the future.
* Know if it is safe to override unique_ptr's default deleter with a deleter that calls the default.
My lack of understanding is really getting in my way here.
Related Questions
Even though Friendly is declared as a friend within XStMachine in the example code, it has to be forward declared earlier in the program as well. Why does this happen?
Even though Friendly is declared a friend, it cannot access protected member functions of XStMachine. For instance, &XStMachine::tranFunc1 is invalid. Why?
std::function takes only a regular function type as template argument. A pointer-to-member-function type doesn't work.
Below is what might be a typical definition of std::function in the standard library:
template< class >
class function; // intentionally undefined
template< class R, class... Args >
class function<R(Args...)> // actual definition
The template argument doesn't determine what kind of function this instantiation can store, but rather how this instantiation can be called.
Any instantiation attempt with a type that is not a regular function type will produce an incomplete type. Example:
std::function <int> incomplete;
In your code you may either:
store std::function<void(EventData const&)> in the map (use std::bind to construct these objects from a pointer-to-member-function and an object pointer); or
do away with std::function altogether and store pointers-to-member-function in the map directly.
I've the following problem of which I cannot find a solution.
Of course, it could be that a solution does not exist at all, but I'd like to have a try on SO before to give up.
First of all, a snippet that compiles with no errors:
#include <unordered_set>
#include <memory>
struct S {
enum class E: unsigned int { FOO = 0, BAR };
};
namespace std
{
template<>
struct hash<S::E> {
using argument_type = S::E;
using underlying_type = std::underlying_type<argument_type>::type;
using result_type = std::size_t;
result_type operator()(argument_type const &s) const noexcept {
const underlying_type us = static_cast<underlying_type>(s);
hash<underlying_type> hfn;
return hfn(us);
}
};
}
int main() {
std::unordered_set<S::E> set;
}
With this code in mind, I found myself with the requirement of having the unordered_set as a data member of S or, at least, a derived class. A possible working solution is to add add the following lines once the std namespace has been closed:
struct D: public S {
std::unordered_set<S::E> set;
};
Another possible solution is maybe (I've not tried it) to use an unscoped enumeration. Anyway, the first attempt I made was to modify the definition of the struct S as it follows:
struct S {
enum class E: unsigned int { FOO = 0, BAR };
std::unordered_set<E> set;
};
This ends in an error because (if I've correctly understood the problem) the unordered_set requires the specialized hash function. Anyway, the latter requires S::E to be at least declared, thus it is not enough to swap the two pieces of code.
Here the first part of the error log (for it's very long):
In file included from /usr/include/c++/5/bits/hashtable.h:35:0,
from /usr/include/c++/5/unordered_set:47,
from main.cpp:1:
/usr/include/c++/5/bits/hashtable_policy.h: In instantiation of ‘struct std::__detail::__is_noexcept_hash<S::E, std::hash<S::E> >’:
/usr/include/c++/5/type_traits:137:12: required from ‘struct std::__and_<std::__is_fast_hash<std::hash<S::E> >, std::__detail::__is_noexcept_hash<S::E, std::hash<S::E> > >’
/usr/include/c++/5/type_traits:148:38: required from ‘struct std::__not_<std::__and_<std::__is_fast_hash<std::hash<S::E> >, std::__detail::__is_noexcept_hash<S::E, std::hash<S::E> > > >’
/usr/include/c++/5/bits/unordered_set.h:95:63: required from ‘class std::unordered_set<S::E>’
main.cpp:6:27: required from here
/usr/include/c++/5/bits/hashtable_policy.h:85:34: error: no match for call to ‘(const std::hash<S::E>) (const S::E&)’
noexcept(declval<const _Hash&>()(declval<const _Key&>()))>
^
In file included from /usr/include/c++/5/bits/move.h:57:0,
from /usr/include/c++/5/bits/stl_pair.h:59,
from /usr/include/c++/5/utility:70,
from /usr/include/c++/5/unordered_set:38,
from main.cpp:1:
/usr/include/c++/5/type_traits: In instantiation of ‘struct std::__not_<std::__and_<std::__is_fast_hash<std::hash<S::E> >, std::__detail::__is_noexcept_hash<S::E, std::hash<S::E> > > >’:
/usr/include/c++/5/bits/unordered_set.h:95:63: required from ‘class std::unordered_set<S::E>’
main.cpp:6:27: required from here
/usr/include/c++/5/type_traits:148:38: error: ‘value’ is not a member of ‘std::__and_<std::__is_fast_hash<std::hash<S::E> >, std::__detail::__is_noexcept_hash<S::E, std::hash<S::E> > >’
: public integral_constant<bool, !_Pp::value>
^
In file included from /usr/include/c++/5/unordered_set:48:0,
from main.cpp:1:
/usr/include/c++/5/bits/unordered_set.h: In instantiation of ‘class std::unordered_set<S::E>’:
main.cpp:6:27: required from here
/usr/include/c++/5/bits/unordered_set.h:95:63: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<S::E> >, std::__detail::__is_noexcept_hash<S::E, std::hash<S::E> > > >’
typedef __uset_hashtable<_Value, _Hash, _Pred, _Alloc> _Hashtable;
^
/usr/include/c++/5/bits/unordered_set.h:102:45: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<S::E> >, std::__detail::__is_noexcept_hash<S::E, std::hash<S::E> > > >’
typedef typename _Hashtable::key_type key_type;
Usually, in such a case, I can solve with something like a forward declaration, as the one in the example below:
struct B;
struct A { B *link; };
struct B { A *link; };
Unfortunately, I've not been able to do something similar with the enum embedded in a struct and that's why I started this question. Is it possible to solve it, thus avoid to define the derived class D, or deriving is the only viable solution in this case?
You can't forward declare a nested enum, see this answer.
You can do as ForEveR explained, or you can have your generic enum_hash template regardless of std namespace and use it in your data structure, since you are not forced to use std::hash as the hashing function, eg:
template<typename T>
struct enum_hash {
using argument_type = T;
using underlying_type = typename std::underlying_type<argument_type>::type;
using result_type = std::size_t;
result_type operator()(argument_type const &s) const noexcept {
const underlying_type us = static_cast<underlying_type>(s);
std::hash<underlying_type> hfn;
return hfn(us);
}
static_assert(std::is_enum<T>::value, "T must be an enum!");
};
struct S {
enum class E: unsigned int { FOO = 0, BAR };
std::unordered_set<S::E, enum_hash<S::E>> set;
};
You can just write specialization of hash for all enums and then all would work fine.
namespace std {
template<class E>class hash {
using sfinae = typename std::enable_if<std::is_enum<E>::value, E>::type;
public:
size_t operator()(const E&e) const {
return std::hash<typename std::underlying_type<E>::type>()(e);
}
};
};
I'd like a variant contain copies of objects of its type. Somehow it is not working:
struct value
{
};
class json;
using json = ::boost::variant<
::std::vector<::std::unique_ptr<json> >,
::std::unordered_map<::std::string, ::std::unique_ptr<json> >,
value
>;
json.hpp:116:2: error: conflicting declaration 'using json = '
>;
^
json.hpp:110:7: error: 'class json' has a previous declaration as 'class json'
class json;
I know of 2 workarounds already: ::std::unique_ptr<void>, with a custom deleter, as well as the possibility of using ::boost::any instead of the variant, but are these the only ways? The problem with ::boost::any is that I need to enable RTTI for it to work.
What about:
struct json : ::boost::variant<
::std::vector<::std::unique_ptr<json> >,
::std::unordered_map<::std::string, ::std::unique_ptr<json> >,
value
>
{
using variant::variant;
template <typename U>
json& operator=(U&& u)
{
variant::operator=(::std::forward<U>(u));
return *this;
}
};
That would be the solution, except it doesn't work for me with g++ (constructing json out of vector fails because of ambiguous constructor call). Construction from a const reference to such a vector works, but not not from a non-const reference. I have no idea why. In addition, unique_ptr doesn't work with boost::variant for me because it's uncopyable (shared_ptr does work).
In header:
list< SKPair<VALUETYPE> > *values[256];
In implementation:
const list< SKPair<VALUETYPE> > *bucket = values[0];
typename list< SKPair<VALUETYPE> >::iterator it = bucket.begin();
The gcc compiler complains about the second line:
error: request for member ‘begin’ in ‘bucket’, which is of non-class type ‘const std::list<SKPair<int>, std::allocator<SKPair<int> > >*’
(Here in main I create a test instance of my class where VALUETYPE is int.) Any idea what I'm doing wrong?
Write:
typename list< SKPair<VALUETYPE> >::iterator it = bucket->begin();
The -> is needed here.
bucket is declared as a pointer, so you need a dereferencing operator to access its members:
auto it = bucket->begin();
Should do the trick if you have C++11's auto available.