Initializing GTest const class members - c++11

I want to achieve something like this:
class MyTest: public ::testing::Test {
public:
const int myConstInt = 23;
}
TEST_F(MyTest, MyTest1) {... use myConstInt ...}
But recollecting from Item 4 of EffectiveCPP, the initialization is not guaranteed in this manner and there is a chance of undefined behavior.
Let's say the above is Method 1.
I can think of two other methods to achieve this:
Method 2: Initializer list of myConstStr using a MyTest constructor.
Method 3: Make it constexpr - since the value is set at compile time I shouldnt face any initialization issues during runtime.
Which would be the correct way to go about this? Also Effective CPP is a relatively old book - Does the discussion of Item 4 still fully apply?

const int myConstInt = 23;
is a non static data member with a default member initializer
https://en.cppreference.com/w/cpp/language/data_members#Member_initialization
There is absolutely no risk that it is undefined behavior.
The initialization is guaranteed

Post discussion on Cpplang slack , found out that the best solution would be to use a static const for any integral/Enum types - can also use static constexpr but this is essentially the same except in C++17 where static constexpr data members can also be inlined.
Additioal useful Reference: constexpr vs. static const: Which one to prefer?

Related

What exactly is the in-class-initializer?

I've read many text mentioned the in-class-initializer and I've searched many question on stackoverflow, However I didn't found any precise explanation on what is the in-class-initializer. And as far as I understood the variable of build-in type declared outside any function will be default initialized by the compiler, does the in-class-initilizer doing the same action for a declared variable?
Here is a simple example for in-class initialization. It's useful for less typing, especially when more than one constructor signatures are available. It's recommend in the core guidelines, too.
class Foo {
public:
Foo() = default; // No need to initialize data members in the initializer list.
Foo(bool) { /* Do stuff here. */ } // Again, data member already have values.
private:
int bar = 42;
// ^^^^ in-class initialization
int baz{};
// ^^ same, but requests zero initialization
};
As the data members are explicitly initialized, the second part of your questions doesn't really apply to to in-class initialization.

C++ command pattern with large number of params

I am implementing a command pattern implementations with large number of actions and parameters involved. To simplify I am planning to use class that can hold all possible params to module in a map.
class ParamBag {
public:
add(int paramId, shared_ptr<IParam> param);
bool contains(int paramId);
std::shared_ptr<IParam> get(paramId);
private:
int mask;
std::map<int, std::shared_ptr<IParam>> params;
};
One clear downside of this implementation is each param has to extend from IParam interface, can I somehow simplify this.
If the one that uses the param after the get knows the type of the param, then you can use c++17 std::any, or if you must use c++11 you can try boost::any, or if none of those you can resort back to a void*.
The difference is that void* will not fail on a cast to a wrong type, where any_cast would throw an exception, or return nullptr if used with a pointer. You would also need to use a custom deleter in the std::shared_ptr in order to be able to free the void*.

How can I use boost::interprocess::private_node_allocator on a recursive datastructure?

I have a recursive datastructure I want to store in shared memory. Thus far I have got this (simplified):
using namespace boost::interprocess;
typedef allocator<wchar_t,
managed_shared_memory::segment_manager>TCharAllocator;
typedef basic_string<wchar_t, std::char_traits<wchar_t>, TCharAllocator> MyShmString;
class Node;
template<>
struct sizeof_value<Node>
{
static const std::size_t value = *NodeSize*; <---??
};
typedef private_node_allocator<Node, managed_shared_memory::segment_manager> TNodeAllocator;
class Node
{
private:
MyShmString _value;
vector<Node, TNodeAllocator> _children;
};
If you fill in a number for Nodesize it compiles and runs. You can get this number by compiling and printing a sizeof(Node). This is not very robust. I have tried using a forward declared constexpr function returning the size of Node, but this does not compile (on MSVC).
Is there another way to solve this?
If I understand correctly the only source of complication is with declaring datastructures that entail incomplete types.
If the boost::interprocess::sizeof_value<> specialization works, that would be enough.¹
In terms of robustness, it is easy to add a static_assert after the definition of Node has become complete to ensure that the actual value matches the size reported by the compiler:
static_assert(boost::interprocess::sizeof_value<Node>::value == sizeof(Node), "sizeof mismatch");
¹ I have a hunch it can be done without that, but I cannot spend the time to make your code self-contained right now to check

Template template in c++11 error

I've been reading the chapter 5 of "C++ Templates, The complete guide", and i've seen the concept of "template template" templates, so tried myself.
In a template class, i've declared my template like this:
template <typename TipoClave, typename TipoDato,
template <class Elem, class Alloc = allocator<Elem>> class Lista = vector>
And this works. My problem comes when I try to use a different container than the default.
My class is as follows:
class Tabla
{
public:
struct Celda {
TipoClave clave;
TipoDato dato;
};
Tabla(unsigned tam)
{
t.resize(tam);
}
///< Some other functions
private:
typedef Lista<Celda> ListaDatos;
Lista<ListaDatos> t;
};
And then, when I try to use it from the main program like this:
int main (void)
{
Tabla<string,Alumno,array> tabla(200);
///< Some stuff
return 0;
}
But this line Tabla<string,Alumno,array> tabla(200); does not compile, getting me an error like:
test_tabla_t.cpp: In function ‘int main()’: test_tabla_t.cpp:20:27:
error: type/value mismatch at argument 3 in template parameter list
for ‘template class Lista> class Tabla’ Tabla
tabla(200);
I've tried to use Tabla<string,Alumno,vector> tabla(200);, and it works, so I don't know how to solve this error.
Assuming you're trying to use std::array, it does not take an Allocator template parameter. Its second argument is the size of the array.
template<
class T,
std::size_t N
> struct array;
You haven't mentioned how experienced you are with C++, but since you're trying to learn more, I'll say that I've been using C++ for nearly a decade and can count on one hand the number of times I've used template template parameters.
In this case, you want Lista to be "something that acts like a sequence container[1]", you might like to read about concepts[2], which may make it into C++20. They allow you to tell the compiler the interface you want a template parameter to have.
In the meantime, it might be easier to declare Lista as a plain template parameter.
[1] http://en.cppreference.com/w/cpp/concept/SequenceContainer
[2] https://en.wikipedia.org/wiki/Concepts_(C%2B%2B)

Again but without solution: error C2248: 'CObject::CObject' : cannot access private member declared in class 'CObject'

I write a program with my class:
class COrder
{
public:
COrder();
~COrder();
public:
...
CList < CItem > m_oItem;
...
};
which suppose to have list od object of my other class:
class CItem
{
public:
CItem();
~CItem();
public:
int m_i;
double m_d;
CString m_o;
};
and compiler give me error like this in title. Any ideas why ?
In program I use COrder in map:
CMap <CString, LPCTSTR, COrder, COrder> m_map
Quote:
Add copy-constructor and assignment operator to your class COrder.
I add operator= to my class:
COrder& operator=( const COrder oNewOrder )
{
...
m_oItem.AddTail( oNewOrder.m_oItem.GetTail() );
...
return *this;
}
but what you mean by adding "copy-constructor" ?
http://msdn.microsoft.com/en-us/library/ccb3dh5c.aspx i found this but how to implement it in my code. i can't change CList class.
http://www.codeproject.com/Articles/13458/CMap-How-to
Add copy-constructor and assignment operator to your class COrder. This makes the class copyable.
[If class is used in as Key then you need HashKey() and CompareElemenst() in that class]
Also note that STL containers are superior to MFC containers.
You get an error because CMap has default copy-ctor but CMap and CList is derived from CObject and CObject declares private copy constructor and operator=.
So, CMap doesn't offer a copy semantic "out of the box".
I would suggest you to use STL std::map container, which is designed in a
way to implement copy semantic out-of-the-box.
What you don't have with STL out of the box is serialization only.
Note that std::map does not have the confusing ARG_KEY and ARG_VALUE
templates.
std::map just has the Key and Type template arguments (in its basic form).
http://msdn.microsoft.com/en-us/library/s44w4h2s%28VS.80%29.aspx
Or else you can go by the pointer way as Ajay suggested by which you will just shut up the compiler.
The problem statement:
CList<CItem> m_oItem;
And the trigger statement (or some usage):
CMap <CString, LPCTSTR, COrder, COrder> m_map;
Why? Well, CMap would call copy constructor and/or assignment operator for COrder. You didn't provide any, but compiler provides them from your class (i.e. for COrder). This class contains a CList object, which is inherited from CObject. CObject doesn't provide (or better say: Prevents) copy-constructor or assignment operator.
As a result, the compiler raises the error. Unfortunately, the (bad) compiler doesn't give you back-trace of this error.
Best bets for as the solution:
CList < CItem* > m_oItem;
CList<CItem> *m_poItem;
Use or implement your own collection.

Resources