C++ C++;,我可以在编译时静态初始化std::map吗?

C++ C++;,我可以在编译时静态初始化std::map吗?,c++,stl,embedded,C++,Stl,Embedded,如果我给这个编码 std::map<int, char> example = { (1, 'a'), (2, 'b'), (3, 'c') }; std::映射示例={ (1,“a”), (2,'b'), (3,‘c’) }; 然

如果我给这个编码

std::map<int, char> example = {
                                (1, 'a'),
                                (2, 'b'),
                                (3, 'c') 
                              };
std::映射示例={
(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 ‘{...}’   
从括号内的初始值设定项列表中推断需要#包含
在C++98中,“example”必须由构造函数初始化,而不是由“{…}”初始化
这让我有点恼火,因为构造函数是运行时的,理论上可能会失败

当然,如果它这样做了,它将很快失败,并且应该持续这样做,这样我就应该快速找到并纠正问题

但是,我仍然很好奇——在编译时是否有初始化映射、向量等的方法


编辑:我应该说我是为嵌入式系统开发的。并非所有处理器都有C++0x编译器。最流行的可能会,但我不想遇到一个问题&必须维护2个版本的代码

至于提振,我还没有决定。他们对在嵌入式系统中使用有限状态机类缺乏信心,所以这就是我在这里编写的事件/状态/Fsm类


唉,我想我最好谨慎行事,但我希望这次讨论对其他人有所帮助。

不是在C++98中。C++11支持这一点,因此如果启用C++11标志并包含g++建议的内容,则可以

编辑:从gcc 5默认情况下,C++11处于启用状态

您可以使用库:

#包括
#包括
int main()
{
std::映射示例=
boost::assign::map_list_of(1,'a')(2,'b')(3,'c');
}

然而,正如Neil和其他人在下面的评论中指出的那样,这种初始化是在运行时进行的,与UncleBean的建议类似。

对于C++0x,您可能需要一直使用大括号(对于每一对也使用新的语法):

std::map示例={{1,'a'},{2,'b'},{3,'c'};
用于构造对的括号没有意义。或者,您可以完全命名每一对或使用make_对(就像您在C++98中所做的那样)

std::映射示例={
std::make_对(1,'a'),
std::使_对(2,'b'),
std::组成配对(3,'c')
};
至于在编译时创建这些实例:没有。STL容器都完全封装了运行时内存管理

我想,您只有一个编译时映射,其中包含boost的元编程之类的库(如果完全正确,则不是100%确定,而且还没有研究它有什么好处):

使用名称空间boost::mpl;
地图<
一对
一对
一对
>编制时间图;

对于C++0x之前的版本,最接近的方法是不使用为运行时使用而设计的容器(并将自己限制为基本类型和聚合):

然后,可以使用某种映射视图来访问它,或者您可以实现一个包装器,该包装器允许进行类似于所做的聚合初始化

当然,问题是这些好处是否值得花时间来实施

如果我在这里的阅读是正确的,C++0x初始值设定项列表可能会为您提供非聚合的静态初始化,如
std::map
std::pair
,但前提是与动态初始化相比,这不会改变语义。

因此,在我看来,如果您的实现能够通过静态分析验证,如果
映射是静态初始化的,但不能保证行为不会发生变化,那么您似乎只能得到您想要的结果。

有一个技巧可以使用,但前提是此数据不会在任何其他静态构造函数中使用。 首先定义一个简单的类,如下所示:

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);

然后,像这样使用它:

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);
std::地图编号;
void uu initNumsFunc()
{
数字[“一”]=1;
数字[“两”]=2;
数字[“三”]=3;
}
初始值设定项&uuuinitnums(&&uuuuinitnumsfunc);


当然,这有点过头了,所以我建议您仅在必要时使用它。

这不是完全的静态初始化,但还是要尝试一下。 如果您的编译器不支持C++0x,我会选择std::map的迭代构造函数:

std::对映射_数据[]={
标准::制造成对(1,“a”),
标准::制造成对(2,“b”),
标准:制造成对(3,“c”)
};
映射我的映射(映射数据,
地图数据+地图数据大小/地图数据大小[0];

这是非常可读的,不需要任何额外的库,应该可以在所有编译器中使用。

没有标准方法在编译时初始化
std::map
。正如其他人提到的,如果可能,C++0x将允许编译器将初始化优化为静态,但这永远无法保证

但是请记住,STL只是一个接口规范。您可以创建自己的兼容容器,并为它们提供静态初始化功能

根据您是否计划升级编译器和STL实现(特别是在嵌入式平台上),您甚至可以深入研究正在使用的实现,添加派生类,然后使用它们

模板结构映射{enum{value=N};};
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 ;
模板结构映射{enum{value=(int)'a'};}; 模板结构映射{enum{value=(int)'b'};}; 模板结构映射{enum{value=(int)'c'};};
std::cout-Yes这是一个缺失了很长时间的特性。我真的希望C++0x变成C++OA,这样我们就可以开始向我们的编译器供应商提出要求了。嗯,如果我读对了,如果语义没有改变,实现也可以静态初始化非聚合。如果静态分析不能保证这一点,C++0x初始值设定项列表将不会改变任何事情。@daramarak:我认为编译器供应商是编写标准的供应商;v) ,无论您是否要求,支持应该在主要编译器中的规范之后立即提供,对于次要编译器,祝您好运;我敢打赌没有人会相信
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);
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]);
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 ;