Static assert on size of static const member - c++11

I'm trying to put a static assert on the size of static const unordered_map member. But I get an error saying non-const condition for static assertion. Could someone help?
#include<unordered_map>
#include<string>
using namespace std;
class A{
public:
static const unordered_map<string,string> strMap;
};
const unordered_map<string,string> A::strMap ={{"key","value"}};
int main() {
static_assert(A::strMap.size() == 1, "sizes don't match");
}
EDIT: Based on the comments, I want to clarify, the following code works fine (it uses an array instead of a map):
#include<unordered_map>
#include<string>
using namespace std;
class A{
public:
static const pair<string,string> strMap[];
};
const pair<string,string> A::strMap[] ={{"key","value"}};
int main() {
//static_assert(sizeof(A::strMap)/sizeof(A::strMap[0]) == 2, "sizes don't match"); Fails to compile
static_assert(sizeof(A::strMap)/sizeof(A::strMap[0]) == 1, "sizes don't match"); //Compiles fine
}

Can't do this. You'd need constexpr std::unordered_map for this, and this is not possible, since it's constructor is not constexpr. And of course, no class which allocates memory (unordered_map being of this kind) can declare it's constructor constexpr.

Related

c++11 template metaprogramming construct a std::unorderer_map at compile time

i trying to develop a Finite State Machine with template meta programming techniques, but i getting stuck with a map that it has to be fill at compile time, this the code(gcc 4.8 c++11):
#include <functional>
#include <type_traits>
#include <iostream>
#include <unordered_map>
namespace NSStateMachine {
//Definicion de estado unidad
template<class FSM, class From, class Event, class TO, bool(FSM::* transicion_fn)(const Event &)>
struct Transition
{
using FSM_TYPE=FSM;
using FROM_STATE= From;
using EVENT_TYPE= Event;
using TO_STATE_TYPE=TO;
using EVENT_BASE_TYPE = typename Event::BASE_TYPE;
static bool do_transition(FSM_TYPE& currenState, EVENT_BASE_TYPE const& aEvent)
{
return (currenState.*transicion_fn)(static_cast<EVENT_TYPE const&>(aEvent));
}
};
//States
template<class Transition, const Transition * const TransitionPtr, class ... Args>
class StateMachine
{
public:
StateMachine():transitionMap{{static_cast<typename Transition::TransitionID>(*TransitionPtr::TransitionID_Value),nullptr}}
{}
template<class Event>
bool evalEvent(const Event & aEvent)
{
std::cout<<"evento recibido"<<std::endl;
}
std::unordered_map<typename Transition::TransitionID, const Transition * const > transitionMap ;
};
}
int main()
{
//it doesnt compile, i canoot create the state machine
return 0;
}
The compile error:
error: 'TransitionPtr' is not a class, namespace, or enumeration
StateMachine():transitionMap{{static_cast<typename Transition::TransitionID>(*TransitionPtr::TransitionID_Value),nullptr}}
^
The problem seem to be in the line
transitionMap{{static_cast<typename Transition::TransitionID>(*TransitionPtr::TransitionID_Value),nullptr}}
i will try to init the unorderer_map with the automatic constructor.
i have defined this Transition::TransitionID as a class variable defined in the class represented by the template argument
I will really appreciate any help.
Thx!!!!
i have already test with default types , it compile and work this
The error message is pretty clear. TransitionPtr is a pointer, not a type, so you can't use it to the left of :: in TransitionPtr::TransitionID_Value.
Also, I don't think you'll find a way to initialize an unordered_set at compile time, since it doesn't have constexpr constructors and in general almost certainly uses heap allocations.

Error during cast of an object to std::string with proper operator-overloading

Follwing short programm will run perfect with VS 2013 and reach the marked point. But in XCode the compiler will show an error due ambiguous constructor. How to work around?
#include <iostream>
#include <string>
class atest
{
public:
explicit operator const char *()
{
return "";
}
template<class T> operator T()
{
}
operator std::string()
{
return std::string("Huhuhu");
}
template<class T> atest &operator =(T value)
{
}
atest &operator =(const std::string &value)
{
return *this; // I want to reach this point
}
};
int main(int argc, char* argv[])
{
atest tst;
// auto a = (std::string)tst;
std::string astr;
// do some stuff
astr=tst; // I wanna keep this line
return 0;
}
Clang is not able to distinguish between different constructor where VS2013 is taking the right one. I search now for a way to exclude the "const char *" template of the assignment operator.
std::string have multiple constructors taking single arguments, and since you provide both a conversion operator for std::string and a generic any-type conversion operator, the compiler simply don't know which constructor to pick.
I think you have written far too many overloaded functions. The only function you need is this:
operator std::string()
{
return std::string("Huhuhu");
}
Comment rest all and your code would work just fine.

Error with cast operator and std::string in a class

I broke down a problem I already tried to explain here in following problem:
#include <iostream>
#include <string>
class atest
{
public:
operator std::string()
{
return std::string("Huhuhu");
}
operator int()
{
return 42;
}
};
int main(int argc, char* argv[])
{
atest tst;
std::string astr;
astr=tst;
int i=0;
i=tst;
return 0;
}
std::string seems to have several constructors which even cover int. I got a class which need to be cast able to std::string but also to an integral type. As the assign (=) operator is not overide able outside a class definition I got no Idea how to get the above program running.
It is bad design but it is worth noting that VS2013 has no problem with above code.
You can use explicit conversion
explicit operator std::string()
~~~~~~~
{
return std::string("Huhuhu");
}

Why is Visual Studio using std::iterator<> instead of mine::iterator<>

I've been trying to figure out this problem for a couple days now and finally figured it out after striping everything down to the code below. You'll see in the code below three different attempts at a constructor for const_iterator, along with the errors I get on two of them. It appears to me that the compiler is trying to use std::iterator instead of the locally declared mine::iterator. Is it supposed to be that way?
Other tidbits that have given clues:
If I name mine::iterator something else, like mine::B, then const_iterator(const B &rhs) works.
If I derive const_iterator from a class other than std::iterator, then const_iterator(const iterator<T> &rhs) works.
Thanks for any info. Here's the code:
#include "stdafx.h"
#include <iterator>
namespace mine
{
template <class T>
class iterator : public std::iterator<std::random_access_iterator_tag, T, ptrdiff_t, T*, T&>
{
public:
iterator() {}
};
template <class T>
class const_iterator : public std::iterator<std::random_access_iterator_tag, T, ptrdiff_t, const T*, const T&>
{
public:
const_iterator() {}
const_iterator(const mine::iterator<T> &rhs) {} // works
//const_iterator(const iterator &rhs) {} // error C2440: initializing: cannot convert from 'mine::iterator<T>' to 'mine::const_iterator<T>'
//const_iterator(const iterator<T> &rhs) {} // error C2976: std::iterator: too few template arguments
};
}// namespace mine
using namespace mine;
int _tmain(int argc, _TCHAR* argv[])
{
iterator<int> y;
const_iterator<int> x = y;
return 0;
}
First of all 'using namespace' is evil, use typedef for ease of use. for example instead of saying iterator use mine::iterator.
Also your second point gives the answer of your question. "If I derive const_iterator from a class other than std::iterator, then const_iterator(const iterator<T> &rhs) works."
Here the nearest iterator belongs to std not mine, as std::iterator is the base class of your const_iterator.

How to remove unique_ptr by pointer from a container?

Creating an object and giving ownership to a container using a unique_ptr is no problem. How would one remove an element by raw pointer?
std::set<std::unique_ptr<MyClass>> mySet;
MyClass *myClass = new MyClass();
mySet.insert(std::unique_ptr<MyClass>(myClass));
// remove myClass from mySet?
You will need to find the iterator corresponding to the myClass element and then pass that iterator to mySet.erase(). The iterator may be found using the std::find_if algorithm with a custom Predicate functor that understands how to dereference unique_ptr and compare it to the raw pointer myClass.
You can not use the overloaded size_t set::erase ( const key_type& x ); since the raw pointer (even if wrapped in a temporary unique_ptr) will not be found in mySet.
Not as pretty as I would've liked. But the following does the job:
#include <memory>
#include <set>
#include <iostream>
struct do_nothing
{
void operator()(const void*) const {}
};
struct MyClass
{
MyClass() {std::cout << "MyClass()\n";}
MyClass(const MyClass&) {std::cout << "MyClass(const MyClass&)\n";}
~MyClass() {std::cout << "~MyClass()\n";}
};
int main()
{
std::set<std::unique_ptr<MyClass>> mySet;
MyClass *myClass = new MyClass();
mySet.insert(std::unique_ptr<MyClass>(myClass));
// remove myClass from mySet?
std::set<std::unique_ptr<MyClass>>::iterator i =
lower_bound(mySet.begin(), mySet.end(),
std::unique_ptr<MyClass, do_nothing>(myClass));
if (i != mySet.end() && *i == std::unique_ptr<MyClass, do_nothing>(myClass))
mySet.erase(i);
}
It seems i am able to retrieve an iterator using a custom Predicate with lower_bound. Since std::set is an ordered container, lower_bound should perform logarithmically.
std::set<std::unique_ptr<MyClass>>::iterator i =
std::lower_bound(mySet.begin(), mySet.end(), myClass, MyPredicate<MyClass>());
template<class Type>
struct MyPredicate
{
bool operator()(const std::unique_ptr<Type>& left, const Type* right) const
{
return left.get() < right;
}
}
Still not the best solution but for the moment i go with:
PointerMap<MyFoo>::Type myFoos;
MyFoo * myFoo = new MyFoo();
myFoos.insert(PointerMap<MyFoo>::Item(myFoo));
The header is:
#include <map>
#include <memory>
#include <utility>
template<typename T>
struct PointerMap
{
typedef std::map<T *, std::unique_ptr<T>> Type;
struct Item : std::pair<T *, std::unique_ptr<T>>
{
Item(T * pointer)
: std::pair<T *, std::unique_ptr<T>>(pointer, std::unique_ptr<T>(pointer))
{
}
};
};
You might like the answer over here: Efficiently erase a unique_ptr from an unordered_set
That's for C++14, but I think applies to C++11 as well.
It is not pretty, but does the efficient thing — no scanning the container, but using proper hash-based lookup.

Resources