Two-phase lookup: can I avoid "code bloat"? - c++

Two-phase lookup question:
Is there a more synthetic way to write this code, i.e. avoiding all those using directives?
Something like using CBase<T>; is what I would like, but it is not accepted.
#include <iostream>
template <typename T>
class CBase
{
protected:
int a, b, c, d; // many more...
public:
CBase() {
a = 123; c = 0;
}
};
template <typename T>
class CDer : public CBase<T>
{
// using CBase<T>; // error, but this is what I would like
using CBase<T>::a;
using CBase<T>::b;
//...
public:
CDer() {
std::cout << a << this->c;
}
};
int main()
{
CDer<int> cd;
}
In my real code there are many more member variables/functions, and I was wondering if it is possible to write shorter code in some way.
Of course, using the this->c syntax does not solve the problem...
Thank's!
gcc 4.1
MacOS X 10.6

I reduced the testcase and then consider three options
template<typename T> struct Base { int a; };
Option 1
template<typename T> struct Der : Base<T> {
void f() {
int &ra = Der::a;
// now use ra
}
}
Option 2
template<typename T> struct Der : Base<T> {
void f() {
// use this->a instead
// or Der::a
}
}
Option 3
// use your using declarations

It doesn't look like most of those variables are parameterized. Does CBase use them all, or just a? If not, move them into a new non-template base of CDer.
Or, pack them all into a POD struct and then using CBase<T>::m_ints;.
High overhead solution: non-templated virtual base.
Not sure but worth a try: nest the definition of CDer inside CBase and then typedef it into namespace scope.

Related

Initialization block to be run after constructors

Let's say I have the below class:
template <class Base>
struct Wrapper : public Base {
using Base::Base;
// ... add functionality ...
};
And I want some code to be executed during construction after constructors. I can't add a default constructor, because it won't be run when an inherited constructor is used. One idea is this:
template <class Base>
struct Wrapper : public Base {
bool _ = [this] {
// initialize ...
return true;
}();
using Base::Base;
};
This does work perfectly well as long as you place it as the last member, but it wastes memory.
Another way is:
#include <type_traits>
template <class T>
struct InitBlock {
InitBlock() {
static_cast<T*>(this)->init();
}
};
template <class Base>
struct Wrapper : public Base, private InitBlock<Wrapper<Base>> {
private:
template <class T>
friend struct InitBlock;
void init() {
// initialize ...
}
public:
using Base::Base;
};
Which is good, but a bit verbose. And there is nothing protecting init from being called again elsewhere. Also, if Wrapper adds members, this is called before those are initialized, so it's not ideal.
What is a better (safe and low on boilerplate) way of doing this?
As mentioned, we can use [[no_unique_address]] to avoid allocating memory for an empty class. It is honored by all major compilers, except for MSVC. MSVC has its own extension of [[msvc::no_unique_address]]. We wrap a macro around this, and it works fine:
#include <stdio.h>
#ifdef _MSC_VER
#define NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
#else
#define NO_UNIQUE_ADDRESS [[no_unique_address]]
#endif
template <class Base>
struct Wrapper : public Base {
private:
NO_UNIQUE_ADDRESS struct Init {} _ = [] {
puts("Wrapper init");
return Init{};
}();
public:
using Base::Base;
};
struct Foo {
int i;
Foo(int i) : i(i) {
printf("Foo(%d)\n", i);
}
};
int main() {
Wrapper<Foo> wfoo(42);
Foo foo(43);
static_assert(sizeof(wfoo) == sizeof(foo));
}
You still have to take care to place it after all other members to make sure they're initialized by the time we touch them, so it's not ideal.
See online

Is it possible to pass a contexpr value into a constructor? [duplicate]

I've a class that must depend for some reasons from an int template parameter.
For the same reasons, that parameter cannot be part of the parameter list for the class, instead it is part of the parameter list of its constructor (that is, of course, templated).
Here the problems arose.
Maybe I'm missing something, but I can't see an easy way to provide such a parameter to the constructor, because it cannot be deduced nor explicitly specified.
So far, I've found the following alternatives:
put the above mentioned parameter into the parameter list of the class
create a factory method or a factory function which can be invoked as an example as factory<42>(params)
provide a traits struct to the constructor
I tried to create a (not so) minimal, working example for the last mentioned solution, also in order to explain better the problem.
The class in the example is not a template class for itself, for the key point is the constructor, anyway the real one is a template class.
#include<iostream>
#include<array>
template<int N>
struct traits {
static constexpr int size = N;
};
class C final {
struct B {
virtual ~B() = default;
virtual void foo() = 0;
};
template<int N>
struct D: public B{
void foo() {
using namespace std;
cout << N << endl;
}
std::array<int, N> arr;
};
public:
template<typename T>
explicit C(T) {
b = new D<T::size>{};
}
~C() { delete b; }
void foo() { b->foo(); }
private:
B *b;
};
int main() {
C c{traits<3>{}};
c.foo();
}
To be honest, none of the solutions above mentioned fits well:
moving the parameter into the parameter list of the class breaks completely its design and is not a viable solution
a factory method is something I'd like to avoid, but it could solve the issue
the traits struct seems to be the best solution so far, but somehow I'm not completely satisfied
The question is pretty easy: is there something I missed out there, maybe an easier, more elegant solution, a detail of the language I completely forgot, or are the three approaches mentioned above the ones from which I must choice?
Any suggestion would be appreciated.
You have to pass in something that can be deduced. The simplest thing to use is just a empty wrapper for an int: std::integral_constant. Since you only want ints I believe, we can alias it and then only accept that specific type:
template <int N>
using int_ = std::integral_constant<int, N>;
Where your C constructor just accepts that:
template <int N>
explicit C(int_<N> ) {
b = new D<N>{};
}
C c{int_<3>{}};
You could even go all out and create a user-defined literal for this (a la Boost.Hana) so that you can write:
auto c = 3_c; // does the above
Also, consider simply forwarding the trait through to D. Metaprogramming works better if everything everywhere is a type. That is, still accept the same int_ in C:
template <class T>
explicit C(T ) {
b = new D<T>{};
}
Where now D expects something that has a ::value:
template <class T>
struct D: public B{
static constexpr int N = T::value;
void foo() {
using namespace std;
cout << N << endl;
}
std::array<int, N> arr;
};
It's the same thing either way from the user of C's perspective, but just worth a thought.
I think that solution with "traits" is the best for most cases.
Only to make a little more "mess" in this issue I will provide two more alternatives. Maybe in some very specific cases - they can be in some way better.
Template global variable - you can name it a prototype solution:
class C only differs in its constructor from your original code:
class C final {
// All B and D defined as in OP code
public:
// Here the change - c-tor just accepts D<int>
template <int size>
explicit C(D<size>* b) : b(b) {}
// all the rest as in OP code
};
The prototype - template global variable:
template <int N>
C c{new C::D<N>()};
// this variable should be rather const - but foo() is not const
// and copy semantic is not implemented...
And usage:
int main() {
// you did not implement copy semantic properly - so just reference taken
C& c = ::c<3>;
c.foo();
}
Solution with Base class - and derive class depending on int
This solution, although looks pretty promising I would personally avoid - that only complicates design - and some possibility of object slicing is here present too.
class CBase {
// all here as in OP code for C class
public:
// only difference is this constructor:
template<int size>
explicit CBase(D<size>* b) : b(b) {}
};
Then - the final class:
template <int N>
class C final : private CBase {
public:
C() : CBase(new CBase::D<N>()) {}
using CBase::foo;
};
The usage:
int main() {
C<3> c;
c.foo();
}
Q: One can ask in which way solution with Base class is better than just adding int as another parameter.
A: by base implementation class you do not need to have many "copies" of the same code - you avoid template code bloat...
use template specialization and inheritance:
#include <iostream>
using namespace std;
template <int num> struct A {
A() { cout << "generic" << endl; }
};
template <> struct A<1> {
A() { cout << "implementation of 1" << endl; }
};
template <int num>
struct B : public A<num> {
B() : A<num>() {}
};
int main(int argc, char *argv[])
{
B<1> b;
B<3> b1;
B<4> b2;
}
edit: or you can do it even easier:
template <int num>
struct A {
A();
};
template <int num>
A<num>::A() { cout << "general " << num << endl; }
template <>
A<1>::A() { cout << "specialization for 1" << endl; }

How to use gmock to mock a template method from a class?

How to use gmock to mock a template method (not a template class) for a class? Example a class like this, I want to mock this class, and this template method..
class A{
public:
template<EnumType ENUM_VALUE>
int getType(int val);
};
I know how to mock a class with non-virtual methods, or mock a templated class, but i dont know how to mock a non-templated class with a templated method..
First much better solution is to use the implementation of this function A::getType - maybe it does not have to be mocked? E.g.: if it just returns some value that is set in constructor - then just construct A in the way that is needed in your test case:
class A{
public:
A(int a) : a(a) {}
template<typename T>
int getType(int val)
{
return a + val;
}
private:
int a;
};
TEST(...)
{
A a(TYPE_VALUE_FOR_TEST);
...
}
If it cannot be done that way - then you might consider to have some instrumentation for UT that is switched with preprocessor macros:
#ifdef TESTING
namespace Testing
{
using std::pair<std::type_index, int> AGetTypeKey;
std::map<AGetTypeKey, int> AGetTypeExpectedValues;
template <typename T>
void expectAGetType(int inputValue, int expectedResult)
{
AGetTypeExpectedValues[AGetTypeKey(std::type_index(typeid(T)), inputValue)] = expectedResult;
}
template <typename T>
int getAGetType(int value)
{
return AGetTypeExpectedValues[AGetTypeKey(std::type_index(typeid(T)), inputValue)];
}
}
#endif
class A{
public:
A(int a) : a(a) {}
template<typename T>
int getType(int val)
{
#if TESTING
return Testing::getAGetType<T>(val);
#else
// your "normal" implementation
...
#endif
}
private:
int a;
};
// compiled with -DTESTING=1
#ifndef TESTING
#error ...
#endif
TEST(...)
{
Testing::expectAGetType<float>(EXPECTED_INPUT_VALUE,
TYPE_VALUE_FOR_FLOAT);
...
}
Regarding point-2 - of course all testing code should be carefully separated from "normal code" - e.g. in some separated header files.
It is worth to say that none of these solution is perfect - and this second solution might not be 100% reliable as you would test not real code but some testable version of it.
Maybe you should start from rethinking your design - as it seems the design was not completed with "design for testability" in mind.
I end up doing a relay to mock the method
E.g.
class MOCK_A{
public:
template<Enum ENUM_VALUE>
int getType(int val){
getType(val, ENUM_VALUE);
}
MOCK_METHOD1(getType, int(int val, Enum enum_value));
};

How can I access a protected constructor from a friend function?

I created a class and I want to force anyone who's trying to construct an object, to use unique_ptr. To do that I thought of declaring the constructor protected and use a friend function that returns a unique_ptr. So here's an example of what I want to do:
template <typename T>
class A
{
public:
friend std::unique_ptr<A<T>> CreateA<T>(int myarg);
protected:
A(int myarg) {}
};
template <typename T>
std::unique_ptr<A<T>> CreateA(int myarg)
{
// Since I declared CreateA as a friend I thought I
// would be able to do that
return std::make_unique<A<T>>(myarg);
}
I did some reading on friend functions and I understood that a friend function provides access to private/protected members of an object of a class.
Is there anyway I can make my example work?
Even without friend functions, my goal is to make the CreateA the only way for someone to create an object.
EDIT
I change the code a bit. I didn't mention that my class takes one template parameter. That makes things more complex apparently.
You can do it this way :-
#include <iostream>
#include <memory>
using namespace std;
class A
{
int arg;
public:
friend unique_ptr<A> CreateA(int myarg);
void showarg() { cout<<arg; }
protected:
A(int myarg): arg(myarg) {}
};
unique_ptr<A> CreateA (int myarg)
{
return std::unique_ptr<A>(new A(myarg));
}
int main()
{
int x=5;
unique_ptr<A> u = CreateA(x);
u->showarg();
return 0;
}
Output :-
5
If you don't want to use friend function you can make the function static & call it like this :-
unique_ptr<A> u = A::CreateA(x);
EDIT :-
In reply to your edit I rewrote the program & it goes like this :-
#include <iostream>
#include <memory>
using namespace std;
template <typename T>
class A
{
T arg;
public:
static std::unique_ptr<A> CreateA(T myarg)
{
return std::unique_ptr<A>( new A(myarg) );
}
void showarg()
{
cout<<arg;
}
protected:
A(T myarg): arg(myarg) {}
};
int main()
{
int x=5;
auto u = A<int>::CreateA(x);
u->showarg();
return 0;
}
Simple & easy !!! But remember you cannot instantiate the object of A. Good Luck !!!
The other answers suggest using a static template function, which I agree is the best solution, because it is simpler.
My answer explains why your friend approach didn't work and how to use the friend approach correctly.
There are two problems in your original code. One is that make_unique is not actually a friend of A, so the call make_unique<A<T>>(myarg); does not have access to A's protected constructor. To avoid this , you can use unique_ptr<A<T>>(new A(myarg)) instead. Theoretically it would be possible to declare make_unique a friend but I'm not even sure of the right syntax for that.
The other issue is the template friends problem. Inside a class template, friend <function-declaration> actually declares a non-template friend.
The C++ FAQ suggests two possible workarounds. One of them is to define the friend function inline. However, in that case the function can only be found by argument-dependent lookup. But since the function does not take A<T> (or A<T> &) as argument, it can never be found this way. So this option is not viable to your situation -- it's more suited to operator overloading.
So the only fix is to declare (and optionally define) the template function before the class definition:
#include <memory>
template<typename T>
class A;
template <typename T>
std::unique_ptr<A<T>> CreateA(int myarg)
{
return std::unique_ptr<A<T>>{new A<T>(myarg)};
}
template <typename T>
class A
{
friend std::unique_ptr<A<T>> CreateA <> (int myarg);
// refers to existing template ^^
protected:
A(int myarg) {}
};
int main()
{
auto x = CreateA<int>(5);
}
Note: It is possible to declare CreateA where I have defined it, and put the function definition later. However, the code I have posted works -- despite A not being defined when new A<T>(myarg) appears in the source -- because CreateA is not instantiated until it is called, at which point A will be defined.
Create a static function that instantiates the protected constructor.
#include<iostream>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include <memory>
using namespace std;
template< typename T >
class A
{
public:
static void CreateA(int myarg, std::unique_ptr<A<T>>& objA, T t) {
std::unique_ptr<A<T>> objB(new A(myarg, t));
objA = std::move(objB);
}
protected:
A(int myarg, T t) {
m_t = t;
}
private:
T m_t;
};
int main() {
int myArg = 0;
std::unique_ptr<A<int>> anotherObjA;
A<int>::CreateA(myArg, anotherObjA, myArg);
return 0;
}

Why is it that defining boost::shared_ptr of a templated behaves differently than boost::shared_ptr of a non templated class

I was trying to integrate the boost::share_ptr into a pair of templated classes that were originally derived from a boost::asio example I found. When I define a type within one class which is a shared::ptr of that class. I can't seem to reference the type in another templated class. If I remove templates from the code, it all compiles.
This won't compile:
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
using namespace std;
template <typename TSomething1>
class SomeTemplateT : public boost::enable_shared_from_this<SomeTemplateT<TSomething1> >
{
public:
typedef boost::shared_ptr<SomeTemplateT<TSomething1> > Ptr;
static Ptr Create()
{
return Ptr(new SomeTemplateT<TSomething1>());
}
SomeTemplateT()
{
cout << "SomeTemplateT created" << endl;
}
};
template <typename TSomething>
class OtherTemplateT
{
public:
OtherTemplateT()
{
// COMPILATION ERROR HERE
SomeTemplateT<TSomething>::Ptr someTemplate = SomeTemplateT<TSomething>::Create();
}
private:
};
The code above yields the following compilation error:
src\Templates\main.cpp: In constructor 'OtherTemplateT<TSomething>::OtherTemplateT()':
src\comps\oamp\src\Templates\main.cpp:30: error: expected ';' before 'someTemplate'
Taking virtually the same code without templates compiles without difficulty:
class SomeTemplateT : public boost::enable_shared_from_this<SomeTemplateT>
{
public:
typedef boost::shared_ptr<SomeTemplateT> Ptr;
static Ptr Create()
{
return Ptr(new SomeTemplateT());
}
SomeTemplateT()
{
cout << "SomeTemplateT created" << endl;
}
};
class OtherTemplateT
{
public:
OtherTemplateT()
{
SomeTemplateT::Ptr someTemplate = SomeTemplateT::Create();
}
private:
};
Platform information:
I'm using gcc4.4.0 from MinGW on windows XP (Code:Blocks IDE).
Am I doing something wrong?
EDIT:
I forgot to mention that if I replace the use of the Ptr typedef with the full declaration of the shared ptr:
boost::shared_ptr
Everything compiles fine.
Also, I can use the type in code outside the of the template.
SomeTemplateT<TSomething>::Ptr is a dependent name; that is, its definition depends on the template parameter. The compiler can't assume that it's a type name unless you say so:
typename SomeTemplateT<TSomething>::Ptr someTemplate = SomeTemplateT<TSomething>::Create();
^^^^^^^^
You need to use typename:
typename SomeTemplateT<TSomething>::Ptr someTemplate = SomeTemplateT<TSomething>::Create();
This is required to make parsing possible without semantic analysis. Whether SomeTemplateT<TSomething>::Ptr is a type or a member is not known until SomeTemplateT<TSomething> has been compiled.
A example taken from the C++11 Standard (n3290) that demonstrate why the keyword typename (in this context) is useful.
( 14.6 Name resolution [temp.res] )
struct A
{
struct X { };
int X;
};
struct B
{
struct X { };
};
template<class T> void f(T t)
{
typename T::X x;
}
void foo()
{
A a;
B b;
f(b); // OK: T::X refers to B::X
f(a); // error: T::X refers to the data member A::X not the struct A::X
}