如果我编码
std::map<int, char> example = {
(1, 'a'),
(2, 'b'),
(3, 'c')
};
然后g ++对我说
deducing from brace-enclosed initializer list requires #include <initializer_list>
in C++98 ‘example’ must be initialized by constructor, not by ‘{...}’
这让我很烦,因为构造函数是运行时的,理论上可能会失败。
当然,如果确实如此,它会很快失败并且应该一直这样做,所以我应该快速定位&amp;纠正问题。
但是,我仍然很好奇 - 无论如何在编译时初始化地图,矢量等?
编辑:我应该说我正在为嵌入式系统开发。并非所有处理器都具有C ++ 0x编译器。最受欢迎的可能会,但我不想遇到一个问题&amp;必须维护2个版本的代码。
至于Boost,我尚未决定。他们在嵌入式系统中使用他们的有限状态机类是多么的愚蠢,所以这就是我在这里编写的事件/事件/状态/ Fsm类。
叹息,我想我最好安全地玩它,但我希望这个讨论对其他人有帮助。
答案 0 :(得分:37)
这不是完全静态初始化,但仍然试一试。 如果您的编译器不支持C ++ 0x,我会选择std :: map的迭代构造函数:
std::pair<int, std::string> map_data[] = {
std::make_pair(1, "a"),
std::make_pair(2, "b"),
std::make_pair(3, "c")
};
std::map<int, std::string> my_map(map_data,
map_data + sizeof map_data / sizeof map_data[0]);
这非常易读,不需要任何额外的库,并且应该适用于所有编译器。
答案 1 :(得分:21)
不在C ++ 98中。 C ++ 11支持这一点,所以如果你启用C ++ 11标志并包含g ++建议的内容,你可以。
编辑:从gcc 5 C ++ 11默认打开
答案 2 :(得分:14)
您可以使用Boost.Assign库:
#include <boost/assign.hpp>
#include <map>
int main()
{
std::map<int, char> example =
boost::assign::map_list_of(1, 'a') (2, 'b') (3, 'c');
}
然而,正如Neil和其他人在下面的评论中指出的那样,这种初始化发生在运行时,类似于UncleBean的提议。
答案 3 :(得分:13)
使用C ++ 0x,您可能需要一直使用大括号(也为每对使用新式语法):
std::map<int, char> example = { {1,'a'}, {2, 'b'}, {3, 'c'} };
构造对的括号没有意义。或者,您可以完全命名每一对或使用make_pair(就像在C ++ 98中一样)
std::map<int, char> example = {
std::make_pair(1,'a'),
std::make_pair(2, 'b'),
std::make_pair(3, 'c')
};
至于在编译时创建这些实例:没有。 STL容器全部封装了运行时内存管理。
我想,你真的只有一个编译时的地图,里面有像boost的元编程这样的库(不是100%肯定,如果它完全正确,并且没有研究它可能有什么好处):
using namespace boost::mpl;
map<
pair<integral_c<int, 1>, integral_c<char, 'a'> >,
pair<integral_c<int, 2>, integral_c<char, 'b'> >,
pair<integral_c<int, 3>, integral_c<char, 'c'> >
> compile_time_map;
答案 4 :(得分:4)
使用pre-C ++ 0x,最接近的是不使用为运行时使用而设计的容器(并将自己局限于基本类型和聚合):
struct pair { int first; char second; };
pair arr[] = {{1,'a'}, {2,'b'}}; // assuming arr has static storage
然后可以使用某种地图视图访问它,或者您可以实现一个允许聚合初始化类似于Boost.Array的包装器。
当然,问题在于实现这一目标所带来的好处是合理的。
如果我的阅读在这里是正确的,C ++ 0x initializer-lists 可以为你提供非聚合的静态初始化,如std::map
和std::pair
,但仅限于此与动态初始化相比,它不会改变语义
因此,在我看来如果你的实现可以通过静态分析验证如果map
被静态初始化,但没有保证,行为不会改变,那么你只能得到你所要求的内容它发生了。
答案 5 :(得分:1)
您可以使用一种技巧,但前提是此数据不会在任何其他静态构造函数中使用。 首先定义一个这样的简单类:
typedef void (*VoidFunc)();
class Initializer
{
public:
Initializer(const VoidFunc& pF)
{
pF();
}
};
然后,像这样使用它:
std::map<std::string, int> numbers;
void __initNumsFunc()
{
numbers["one"] = 1;
numbers["two"] = 2;
numbers["three"] = 3;
}
Initializer __initNums(&__initNumsFunc);
当然这有点矫枉过正,所以我建议只在你真的需要的时候使用它。
答案 6 :(得分:1)
在编译时没有标准的方法来初始化std::map
。正如其他人所提到的,如果可能的话,C ++ 0x将允许编译器优化初始化为静态,但这永远不会得到保证。
但请记住,STL只是一个接口规范。您可以创建自己的兼容容器并为其提供静态初始化功能。
根据您是否计划升级编译器和STL实现(特别是在嵌入式平台上),您甚至可以深入研究您正在使用的实现,添加派生类并使用它们!
答案 7 :(得分:-2)
template <const int N> struct Map { enum { value = N}; };
template <> struct Map <1> { enum { value = (int)'a'}; };
template <> struct Map <2> { enum { value = (int)'b'}; };
template <> struct Map <3> { enum { value = (int)'c'}; };
std::cout << Map<1>::value ;