C++14 Static class map initialization
You need to "define" your map after you "declared" it:
See: https://en.cppreference.com/w/cpp/language/static
#include <map>
#include <string>
struct SomeInfo
{
std::string id;
std::string name;
};
enum MyEnum {
Enum1, Enum2
};
class Foo
{
private:
static const std::map<MyEnum, SomeInfo> fooMap;
public:
static std::map<MyEnum, SomeInfo> getMap()
{
return fooMap;
}
};
const std::map<MyEnum, SomeInfo> Foo::fooMap = {
{MyEnum::Enum1, SomeInfo{ "info1", "Info 1" }},
{MyEnum::Enum2, SomeInfo{ "info2", "Info 2" }}
};
int main(){
auto val = Foo::getMap()[MyEnum::Enum1];
return 0;
}
And if you want to make your type not constructable you can delete the compiler generated default constructor via Foo() = delete;
- it must not be private.
Initializing a static std::mapint, STRUCTURE in C++
I'd use Boost.Assignment :
#include <boost/assign/list_of.hpp>
...
/* no more temp1, temp2, or PluginDbArray */
...
PluginDB pluginDB = boost::assign::map_list_of
(1, PluginInfo(1, "Adder", ADDER))
(2, PluginInfo(2, "Multiplier", MULTIPLIER));
Initializing a static map using static members
I cannot reproduce this problem with GCC 6.1.0. However, it can be reproduced any time you try to bind a reference to a constexpr
variable you haven't defined, which is probably what your std::map
constructor does :
struct Foo {
static constexpr int i = 42;
};
int main() {
auto const &p = Foo::i; // undefined reference to `Foo::i'
}
This is because binding the reference is an ODR-use of i
, which requires a unique definition to exist at link-time.
There is a simple workaround that works in most such cases, and that is to apply a unary +
:
struct Foo {
static constexpr int i = 42;
};
int main() {
auto const &p = +Foo::i; // OK!
}
Applying +
does not ODR-use i
, since only its value is needed, not its identity. Then the reference binds to the temporary returned by +
, instead of i
.
Initializing a static std::mapint, unique_ptrint in C++
This is one possible implementation:
template <typename T, typename U>
class create_map
{
private:
std::map<T, U> m_map;
public:
create_map(T key, U val)
{
m_map.emplace(std::move(key), std::move(val));
}
create_map&& operator()(T key, U val) &&
{
m_map.emplace(std::move(key), std::move(val));
return std::move(*this);
}
operator std::map<T, U>() &&
{
return std::move(m_map);
}
};
Note the taking argument by value and then moving it into the map with emplace
, and the conversion operator that moves from m_map
.
I don't know if MSVC 2012 supports ref-qualifiers. If it doesn't, you'll need to remove it (that's the two &&
s after the function parameter list). The point of that is to enforce that create_map
should only be used as a temporary. It is possible to also enforce that the conversion operator is only called once, but I didn't do that in the code above.
Now your calls cannot use naked new
s because 1) it isn't exception-safe and 2) raw pointers cannot be implicitly converted to unique_ptr
s. A simple make_unique
implementation that doesn't take arrays into account is
namespace util {
template<class T, class... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
}
You can then change the new MyField<DWORD>()
s to util::make_unique<MyField<DWORD>>()
*.
Demo.
* Using a qualified call disables ADL, which can have surprising effects when you upgrade your compiler if your call has arguments. A full implementation of make_unique
according to the spec can be found in the example code in N3656, the make_unique
proposal paper.
initialize part of a const std::map from another const std::map
While @Rakete111's answer is perfectly valid for what you need, I suggest elevating that to a function. Maybe you can use it multiple places.
std::map<int, std:::string> combine(std::map<int, std::string> const& map1,
std::map<int, std::string> const& map2)
{
std::map<int, std:::string> res(map1);
res.insert(map2.begin(), map2.end());
return res;
}
and then use
const auto secondMap = combine(firstMap,
std::map<int, std::string>{{3, "Third"}});
Initializing a static two dimensional mapint, int in C++
it would be:
map<int, map<int, int>> _map = {
{1, {{2, 100}, {3, 200}}}
};
You could also have:
_map[1] = {{2, 100}, {3, 200}};
Your snippet
map <int, map<int, int>> _map = {
{1, {{2, 100}}},
{1, {{3, 200}}}
};
would be "equivalent" (initialization versus insertion) to:
_map.insert({1, {{2, 100}}});
_map.insert({1, {{3, 200}}}); // Fails as key 1 already present.
Related Topics
How to Use Sdl2 in My Programs Correctly
Convert Python Program to C/C++ Code
How to "Return an Object" in C++
Legality of Cow Std::String Implementation in C++11
Does C++11 Allow Vector≪Const T≫
Pure Virtual Function With Implementation
How to Construct a C++ Fstream from a Posix File Descriptor
How Does C++ Handle &&? (Short-Circuit Evaluation)
What Is the Best Open Xml Parser For C++