I am writing a C++ struct which contains a C-struct. The C-struct is included by other .c files, so I cannot change it to C++.
I want to make sure that every member is of the c++ struct is initialized.
So I have used in-class initialization and constructor initilizer where needed:
struct CppStruct
{
CStruct pod {}; // initialize all members to 0
int i = 0;
double d = 0.0;
CppStruct()
{ }
CppStruct(int another_val)
: i(another_val)
{ }
};
This initializes all the members of the CStruct to zeroes.
Zeroes are fine for most members of the c-struct,
but unfortunately, it also contains a C-enum whithout a zero-value:
// C-header
enum Color { // no '0' entries here!
red = 1,
yellow = 2;
};
struct CStruct { // this struct can potentially contain a lot of members
int i;
int j;
Color col;
int m;
int n;
};
The only way I have found to write the constructor is this, but this theoretically sets the pod.col member twice:
CppStruct()
{ pod.col = Color::red; }
CppStruct(int another_val)
: i(another_val)
{ pod.col = Color::red; }
Is there anyway I can override the initialization of selected members of the pod, without having to specify all its members?
e.g. I tried this but it does not compile:
CppStruct() : pod.col(Color::red) {}
The following is legal, but I want to avoid it,
in case the CStruct is changed/shuffled by another colleague:
CppStruct() : pod{0,0,Color::red,0,0} {}
The best way I think is to just overwrite the col value inside the constructor, don't worry about multiple initializations, as it's just an enum, not a massive object, so the performance difference is somewhat nothing (unless you are really desperate for performance).
A quick and dirty way to achieve initialization the way you wanted is to create a static function that would return a default CStruct like that:
struct CppStruct
{
CStruct pod {}; // initialize all members to 0
int i = 0;
double d = 0.0;
CppStruct()
: pod(_get_default_pod())
{ }
CppStruct(int another_val)
: i(another_val), pod(_get_default_pod())
{ }
private:
static inline CStruct _get_default_pod() {
CStruct pod {};
pod.col = Color::red;
return pod;
};
};
Related
How to store temporary state, needed for the initializer list, in the constructor (on the stack)?
For example, implementing this constructor …
// configabstraction.h
#include <istream>
class ConfigAbstraction
{
public:
ConfigAbstraction(std::istream& input);
private:
int m_x;
int m_y;
int m_z;
};
… using a stateful helper class like this?
// mysillyparserdontworry.h
#include <json/reader.h> //jsoncpp
class MySillyParserDontWorry
{
public:
MySillyParserDontWorry(std::istream& input) { input >> m_parseTree; }
int intByName(const char* name) const { return m_parseTree[name].asInt(); }
private:
Json::Value m_parseTree;
};
My attempt:
// configabstraction.cpp
ConfigAbstraction::ConfigAbstraction(std::istream& input)
: local_parserState(input) // init local variable first: Not possible!
, m_a(local_parserState.intByName("a"))
, m_b(local_parserState.intByName("b"))
, m_c(local_parserState.intByName("c"))
{
MySillyParserDontWorry local_parserState; // ...because it is local
}
With C++11 you could solve this with delegating constructors:
class ConfigAbstraction
{
public:
ConfigAbstraction(std::istream& input);
private:
ConfigAbstraction(const MySillyParserDontWorry& parser);
int m_a;
int m_b;
int m_c;
};
ConfigAbstraction::ConfigAbstraction(const MySillyParserDontWorry& parser)
: m_a{parser.intByName("a")}
, m_b{parser.intByName("b")}
, m_c{parser.intByName("c")}
{
}
ConfigAbstraction::ConfigAbstraction(std::istream& input)
: ConfigAbstraction{MySillyParserDontWorry{input}}
{
}
An alternative solution to your problem would be packing the three individual ints into a common data structure. This would allow you to initialise an object of that type with a private static helper function. Being able to initialise the object instead of assigning to it later also allows for it to be const (if that is required).
Here is an example with std::tuple. But you could also create your own helper struct or even std::array<int, 3>; the basic idea remains the same: have one member object instead of three.
#include <istream>
#include <tuple>
class MySillyParserDontWorry
{
public:
MySillyParserDontWorry(std::istream& input) { /* ... */ }
int intByName(const char* name) const { return /* ... */ 0; }
};
class ConfigAbstraction
{
public:
ConfigAbstraction(std::istream& input);
private:
static std::tuple<int, int, int> parse(std::istream& input)
{
std::tuple<int, int, int> result;
MySillyParserDontWorry parser(input);
std::get<0>(result) = parser.intByName("a");
std::get<1>(result) = parser.intByName("b");
std::get<2>(result) = parser.intByName("c");
return result;
}
std::tuple<int, int, int> const m;
};
ConfigAbstraction::ConfigAbstraction(std::istream& input)
: m(parse(input))
{
}
Why not simply doing the assignments in the constructor's body then?
ConfigAbstraction::ConfigAbstraction(std::istream& input)
: m_a(0)
, m_b(0)
, m_c(0)
{
MySillyParserDontWorry local_parserState;
m_a = local_parserState.intByName("a");
m_b = local_parserState.intByName("b");
m_c = local_parserState.intByName("c");
}
Is there any specific requirement that hinders you doing that?
What an artificial limitation of C++!
It's not an artificial limitation. How should initialisation of local variables be done outside of their function's scope? It would just lead to a great confusion, where variables are actually initialised (naming conflicts aside).
You can not initialize local variables bedfore members. The reason for this is very simple (so that it is NOT an artificial limitation):
Members have to be initialized (constructed) before constructor body begins, because constructor body might access them - and they need to be initialized for this access. On the other hand, local variables do not exist before code enters constructor body (as for any other function).
Conclusion - initialization of local variables before members is impossible.
I use firstly boost::atomic class and there is a initialize problem.
I have a RowActiveData struct
struct RowActiveData {
RowActiveData() : _rowActive(0), _rowActiveFile(0), _rowActiveTrack(1)
{}
size_t _rowActive;
size_t _rowActiveFile;
size_t _rowActiveTrack;
};
and there is RowActive struct use it.
struct IRowActive {
virtual void setRowActive(size_t row) = 0;
};
struct RowActive : public IRowActive {
RowActive() {}
virtual void setRowActive(size_t row)
{
RowActiveData tmpData;
tmpData._rowActive = row;
tmpData._rowActiveFile = row * 2;
tmpData._rowActiveTrack = row * 3;
}
// boost::atomic
// <RowActiveData> _data;
RowActiveData _data;
};
When my process is run, I see everything is fine.
It gives me the values as I expected.
_rowActiveFile is 0 and _rowActiveTrack is 1.
But when I comment out
// RowActiveData _data;
and remove atomic comment out
boost::atomic <RowActiveData> _data;
it gives me garbage values.
What could be wrong?
According to the boost documentation, the empty constrcutor initializes to an unspecified value. Try
boost::atomic<RowActiveData> _data(RowActiveData());
Boost docs are at http://www.boost.org/doc/libs/1_54_0/doc/html/atomic/interface.html
Also, I've checked, and it seems to me that at least the boost implementation in http://www.chaoticmind.net/~hcb/projects/boost.atomic/ would use a char array member instead of RowActiveData, therefore not calling the constructor.
I have a constant value that never changes during run-time, but is impossible to know until run-time.
Is there a way to declare a constant (either as a member of a class or not) without defining it and also assign a computed value once (and only once) it is determined; or am I going to have to resort to a non-const declaration and use coding S & Ps (ALL_CAPS variables names, static declaration if in a class, etc.) to try and keep it from changing?
CLARIFICATION:
Though these are good answers, the real-world situation I have is more complicated:
The program has a main loop that continually runs between processing and rendering; the user can set required options and once they are set they will never change until the program is restart. An "Initialize" function is set up for anything that can be determined before the main loop, but values that are dependent on user interaction must be performed in the middle of the loop during the processing phase. (At the moment, persistent data storage techniques come to mind...)
Something like this?
const int x = calcConstant();
If it's a class member, then use the constructor initialisation list, as in Yuushi's answer.
You can define it in a struct or class and utilize an initialisation list:
#include <iostream>
struct has_const_member
{
const int x;
has_const_member(int x_)
: x(x_)
{ }
};
int main()
{
int foo = 0;
std::cin >> foo;
has_const_member h(foo);
std::cout << h.x << "\n";
return 0;
}
As a static or function-local variable:
const int x = calcConstant();
As a class member:
struct ConstContainer {
ConstContainer(int x) : x(x) {}
const int x;
};
Yes, you can make a private static singleton field with an initialization method and a gettor method. Here's an example of how to do it:
// In foo.h
class Foo
{
public:
// Caller must ensure that initializeGlobalValue
// was already called.
static int getGlobalValue() {
if (!initialized) {
... handle the error ...
}
return global_value;
}
static void initializeGlobalValue(...)
private:
static bool initialized;
static int global_value;
};
// In foo.cpp
bool Foo::initialized = false;
int Foo::global_value;
void Foo::initializeGlobalValue(...) {
if (initialized) {
...handle the error...
}
global_value = ...;
initialized = true;
}
I want to initialize array-of-classes member of a class
const int count = 5;
class In
{
float rate;
public:
In( int index )
{
rate = index / count;
}
};
class Out
{
In ins[count];
public:
Out() : /* ??? */
{
}
};
Can I obtain index of instance of In in initialization ins if I will rely on initialization list of Out::Out()
You can't do that. You need to define a default constructor for In.
Or better yet, use a std::vector.
EDIT: Might be supported in C++11, not sure though.
For a constructor with multiple arguments...
For example:
class C {
public:
C(int a=1, int b=2){ cout << a << ", " << b << "\n"; }
}
int main(){
C a(10), b = 20;
}
output:
10, 2
20, 2
How do I just assign value to the 2nd parameter? So that I can get "1, 20" without knowing the default values? Or is that that I must always assign value to the argument that precedes before I can use the arguments behind?
And how do I implicitly assign all the parameters? If I can't do that, why? For the above example (as I am new to C++), I once thought I would get "10, 20" as output instead.
Or is that that I must always assign value to the argument that precedes before I can use the arguments behind?
Yes. Otherwise, how is the compiler supposed to know which argument should be used for which parameter?
However, there are ways to accomplish this. For example,
struct C {
enum { DefaultA = 1, DefaultB = 2 };
C(int a = DefaultA, int b = DefaultB) { /* ... */ }
};
C object(C::DefaultA, 20);
Or, if you have a lot of parameters with different "defaults:"
struct CParams {
int a, b;
CParams() : a(1), b(2) { }
};
struct C {
C(CParams x) { /* ... */ }
};
CParams params;
params.b = 20;
C object(params);
C++ doesn't support named arguments. You have to specify the first one.
Also, the variable name b from the main function is completely separate from the b in the constructor definition. There's no relationship whatsoever implied by the naming.
I had the same thought (Convienient C++ struct initialisation -- perhaps you find something you like better there) some time ago, but just now, reading your question, I thought of a way to actually accomplish this. But it is quite some extra code, so the question remains if it is actually worth it. I just implemented it very sketchy and I am not proud of my choice of names (I usually don't use _ but it's late). Anyway, this is how you can do it:
#include <iostream>
struct C_members {
int a;
int b;
C_members(int _a, int _b) : a(_a), b(_b) {}
};
class C_init {
public:
virtual C_members get(C_members init) const {
return init;
}
};
class C_a : public C_init {
private:
int a;
public:
C_a(int _a) : a(_a) {}
C_members get(C_members init) const {
init.a = a;
return init;
}
};
class C_b : public C_init {
private:
int b;
public:
C_b(int _b) : b(_b) {}
C_members get(C_members init) const {
init.b = b;
return init;
}
};
class C : private C_members {
private:
static const C_members def;
public:
C(C_init const& ai = C_init(), C_init const& bi = C_init()) : C_members(ai.get(bi.get(def)).a, bi.get(ai.get(def)).b) {
std::cout << a << "," << b << std::endl;
}
};
const C_members C::def(1,2); // default values
// usage:
int main() {
C c1(C_b(77)); // 1,77
C c2(C_a(12)); // 12,2
C c3(C_b(5),C_a(6)); // 6,5
return 0;
}
There is a lot of stuff that can be improved (with templates (for code reduction) and with const refs in the get method), but you get the idea.
As a bonus feature, you almost have the pimpl idiom implemented (very little effort is necessary to extend this to an actual pimpl design).
Usually in OOP, every object instance holds (and represents) a state.
So the best way is to define an accessor functions such as
void setB(int newBvalue);
and also to hold b as a private member.
if "b" is shared among all the instances of the same object, consider to save a static variable.