C++,我可以在编译时静态初始化 std::map 吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2172053/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++, can I statically initialize a std::map at compile time?
提问by Mawg says reinstate Monica
If I code this
如果我编码这个
std::map<int, char> example = {
(1, 'a'),
(2, 'b'),
(3, 'c')
};
then g++ says to me
然后 g++ 对我说
deducing from brace-enclosed initializer list requires #include <initializer_list>
in C++98 ‘example' must be initialized by constructor, not by ‘{...}'
and that annoys me slightly because the constructor is run-time and can, theoretically fail.
这让我有点恼火,因为构造函数是运行时的,理论上可能会失败。
Sure, if it does, it will fail quickly and ought to do so consistently, so that I ought to quickly locate & correct the problem.
当然,如果确实如此,它将很快失败并且应该始终如一地这样做,以便我应该快速定位并纠正问题。
But, still, I am curious - is there anyway to initialize map, vector, etc, at compile time?
但是,我仍然很好奇 - 有没有在编译时初始化地图、向量等?
Edit: I should have said that I am developing for embedded systems. Not all processors will have a C++0x compiler. The most popular probably will, but I don't want to encounter a gotcha & have to maintain 2 versions of the code.
编辑:我应该说我正在为嵌入式系统开发。并非所有处理器都有 C++0x 编译器。最受欢迎的可能会,但我不想遇到问题并且必须维护 2 个版本的代码。
As to Boost, I am undecided. They are wishy-washy on the use of their Finite State Machine classes in embedded systems, so that is actually what I am coding here, Event/State/Fsm classes.
至于Boost,我还没有决定。他们对在嵌入式系统中使用他们的有限状态机类是一厢情愿的,所以这实际上是我在这里编码的,事件/状态/Fsm 类。
Sigh, I guess I'd better just play it safe, but I hope that this discussion has been helpful for others.
唉,我想我最好还是小心一点,但我希望这个讨论对其他人有帮助。
采纳答案by Artyom
Not in C++98. C++11 supports this, so if you enable C++11 flags and include what g++ suggests, you can.
不在 C++98 中。C++11 支持这一点,因此如果您启用 C++11 标志并包含 g++ 建议的内容,则可以。
Edit: from gcc 5 C++11 is on by default
编辑:从 gcc 5 C++11 默认开启
回答by Dmitry
It's not exactly static initialization, but still, give it a try. If your compiler doesn't support C++0x, I'd go for std::map's iteration constructor:
这不是完全静态的初始化,但仍然尝试一下。如果您的编译器不支持 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]);
This is pretty readable, doesn't require any extra libraries and should work in all compilers.
这非常易读,不需要任何额外的库,并且应该适用于所有编译器。
回答by mloskot
You can use Boost.Assignlibrary:
您可以使用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');
}
However, as Neil and others pointed in the comments below, this initialization occurs in runtime, similarly to UncleBean's proposal.
然而,正如 Neil 和其他人在下面的评论中指出的那样,这种初始化发生在运行时,类似于 UncleBean 的提议。
回答by UncleBens
With C++0x you might need to use braces all the way (use the new-style syntax for each pair as well):
对于 C++0x,您可能需要一直使用大括号(也对每一对使用新式语法):
std::map<int, char> example = { {1,'a'}, {2, 'b'}, {3, 'c'} };
Those brackets to construct pairs are not meaningful. Alternatively you can fully name out each pair or use make_pair (as you'd do in C++98)
那些用于构造对的括号没有意义。或者,您可以完全命名每对或使用 make_pair (就像您在 C++98 中所做的那样)
std::map<int, char> example = {
std::make_pair(1,'a'),
std::make_pair(2, 'b'),
std::make_pair(3, 'c')
};
As to creating those instances at compile-time: no. STL containers all encapsulate entirely runtime memory management.
至于在编译时创建这些实例:否。STL 容器都完全封装了运行时内存管理。
I suppose, you'd only really have a compile-time map with libraries like boost's metaprogramming (not 100% sure, if it is entirely correct, and haven't studied what it could be good for):
我想,你真的只有一个带有像 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;
回答by Georg Fritzsche
With pre-C++0x, the closest thing you can get is by not using containers designed for runtime usage (and limiting yourself to fundamental types and aggregates):
对于 C++0x 之前的版本,您可以获得的最接近的结果是不使用为运行时使用而设计的容器(并将自己限制为基本类型和聚合):
struct pair { int first; char second; };
pair arr[] = {{1,'a'}, {2,'b'}}; // assuming arr has static storage
This could then be accessed using some kind of map view, or you could implement a wrapper that allows for aggregate initialization similar to what Boost.Arraydoes.
然后可以使用某种地图视图访问它,或者您可以实现一个包装器,允许类似于Boost.Array所做的聚合初始化。
Of course the question is wether the benefits justify the time put into implementing this.
当然,问题是这些好处是否足以证明为实现这一点所花费的时间是合理的。
If my reading is correct here, C++0x initializer-lists maygive you static initialization of non-aggregates like std::map
and std::pair
, but only if that doesn't change semantics compared to dynamic initialization.
Thus, it seems to meyou can only get what you asked for if your implementation can verify via static analysis that the behaviour doesn't change if the map
is statically initialized, but no guarantees that it happens.
如果我的阅读在这里是正确的,C++0x 初始化列表可能会给你非聚合的静态初始化,比如std::map
and std::pair
,但前提是与动态初始化相比,这不会改变语义。
因此,在我看来,如果您的实现可以通过静态分析验证如果map
静态初始化行为不会改变,您只能得到您所要求的,但不能保证它会发生。
回答by Adis H
There is a trick you can use, but only if this data will not be used in any other static constructor. First define a simple class like this:
您可以使用一个技巧,但前提是此数据不会在任何其他静态构造函数中使用。首先定义一个简单的类,如下所示:
typedef void (*VoidFunc)();
class Initializer
{
public:
Initializer(const VoidFunc& pF)
{
pF();
}
};
Then, use it like this:
然后,像这样使用它:
std::map<std::string, int> numbers;
void __initNumsFunc()
{
numbers["one"] = 1;
numbers["two"] = 2;
numbers["three"] = 3;
}
Initializer __initNums(&__initNumsFunc);
Of course this is a bit overkill so I would recommend using it only if you really have to.
当然,这有点矫枉过正,所以我建议您仅在确实需要时才使用它。
回答by Potatoswatter
There is no standard way to initialize std::map
at compile time. As others have mentioned, C++0x will allow the compiler to optimize the initialization to be static if possible, but that will never be guaranteed.
std::map
在编译时没有初始化的标准方法。正如其他人所提到的,C++0x 将允许编译器在可能的情况下将初始化优化为静态,但这永远无法保证。
Remember, though, that the STL is just an interface spec. You can create your own compliant containers and give them static initialization capability.
但是请记住,STL 只是一个接口规范。您可以创建自己的兼容容器并为其提供静态初始化功能。
Depending on whether you plan on upgrading your compiler and STL implementation (particularly on an embedded platform), you might even just dig into the implementation you're using, add derived classes, and use those!
根据您是否计划升级编译器和 STL 实现(尤其是在嵌入式平台上),您甚至可以深入研究正在使用的实现,添加派生类,然后使用它们!
回答by sreeraj
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 ;