方便的C ++结构初始化

我试图find一个方便的方式来初始化“pod”C ++结构。 现在,考虑下面的结构:

struct FooBar { int foo; float bar; }; // just to make all examples work in C and C++: typedef struct FooBar FooBar; 

如果我想方便地在C(!)中初始化它,我可以简单地写:

 /* A */ FooBar fb = { .foo = 12, .bar = 3.4 }; // illegal C++, legal C 

请注意,我想明确地避免以下表示法,因为如果我在将来更改结构中的任何内容 ,它会使我打破我的脖子:

 /* B */ FooBar fb = { 12, 3.4 }; // legal C++, legal C, bad style? 

为了在C ++中实现和/* A */例子一样的(或者至less类似的),我必须实现一个白痴的构造函数:

 FooBar::FooBar(int foo, float bar) : foo(foo), bar(bar) {} // -> /* C */ FooBar fb(12, 3.4); 

哪个开水好,但不适合懒惰的人(懒惰是件好事,对吗?)。 而且,它和/* B */ example差不多,因为它没有明确指出哪个值到哪个成员。

所以,我的问题基本上是如何在C ++中实现类似于/* A */或更好的function? 或者,我可以解释为什么我不应该这样做(即为什么我的心理范式是不好的)。

编辑

方便的话 ,我的意思是可维护不冗余

由于style A是不允许在C + +,你不想要style B那么使用style BX怎么样:

 FooBar fb = { /*.foo=*/ 12, /*.bar=*/ 3.4 }; // :) 

至less在一定程度上有所帮助。

你的问题有点困难,因为即使是function:

 static FooBar MakeFooBar(int foo, float bar); 

可能被称为:

 FooBar fb = MakeFooBar(3.4, 5); 

因为内置数字types的升级和转换规则。 (C从来没有真正强types)

在C ++中,尽pipe在模板和静态断言的帮助下,您可以实现:

 template <typename Integer, typename Real> FooBar MakeFooBar(Integer foo, Real bar) { static_assert(std::is_same<Integer, int>::value, "foo should be of type int"); static_assert(std::is_same<Real, float>::value, "bar should be of type float"); return { foo, bar }; } 

在C中,你可以命名参数,但你永远不会得到更多。

另一方面,如果你想要的是命名参数,那么你写了很多繁琐的代码:

 struct FooBarMaker { FooBarMaker(int f): _f(f) {} FooBar Bar(float b) const { return FooBar(_f, b); } int _f; }; static FooBarMaker Foo(int f) { return FooBarMaker(f); } // Usage FooBar fb = Foo(5).Bar(3.4); 

如果你喜欢,你可以胡椒types的促销保护。

如果可以的话,使用GCC。 它的C ++ front.end理解C初始化语法。

在C ++中的另一种方式是

 struct Point { private: int x; int y; public: Point& setX(int xIn) { x = Xin; return *this;} Point& setY(int yIn) { y = Yin; return *this;} } Point pt; pt.setX(20).setY(20); 

选项D:

FooBar FooBarMake(int foo, float bar)

法律C,法律C ++。 轻松优化POD。 当然,没有命名参数,但是这就像所有的C ++一样。 如果你想命名参数,Objective C应该是更好的select。

选项E:

 FooBar fb; memset(&fb, 0, sizeof(FooBar)); fb.foo = 4; fb.bar = 15.5f; 

法律C,法律C ++。 命名的参数。

将语句提取到描述它们的函数中(基本重构):

 FooBar fb = { foo(), bar() }; 

我知道风格非常接近你不想使用的风格,但是它可以更容易地replace常量值,并解释它们(因此不需要编辑注释),如果它们改变的话。

你可以做的另一件事(因为你是懒惰的)是使构造函数内联,所以你不必input(除去“Foobar ::”和花费在h和cpp文件之间切换的时间):

 struct FooBar { FooBar(int f, float b) : foo(f), bar(b) {} int foo; float bar; }; 

这个语法怎么样?

 typedef struct { int a; short b; } ABCD; ABCD abc = { abc.a = 5, abc.b = 7 }; 

刚刚在Microsoft Visual C ++ 2015和g ++ 6.0.2上进行了testing。 工作好。
如果你想避免重复variables名称,你也可以制作一个特定的macros。

在C ++中, /* B */也很好,C ++ 0x也将扩展语法,所以它对于C ++容器也是有用的。 我不明白你为什么称它为坏风格?

如果你想使用名字来表示参数,那么你可以使用boost参数库 ,但是它可能会让不熟悉它的人感到困惑。

重新sortingstruct成员就像重新sorting函数参数一样,如果你不仔细地做这些重构,可能会导致问题。