Template collision in constructors - c++

I have a struct defined as follows:
struct A : public B, public C
{
A(const B& b) : B(b), C()
{}
template<typename... Args>
A(Args&&... args) : B(), C(std::forward<Args>(args)...)
{}
};
int main()
{
B b;
A sample1(b);
A sample2(3); // For example, B has a B(int) constructor.
}
And this doesn't work fine, because, A(b) tries use the second constructor (the non-constant reference is the preferred option, and the first constructor is a constant reference), but B hasn't any B(A&).
And moreover, I want to add a move constructor for B:
struct A : public B, public C
{
A(const B& b) : B(b), C()
{}
A(B&& b) : B(std::move(b)), C()
{}
template<typename... Args>
A(Args&&... args) : B(), C(std::forward<Args>(args)...)
{}
};
Now, the last step is to fusion the first two constructors:
struct A : public B, public C
{
template<typename fw_B>
A(fw_B&& b) : B(std::forward<fw_B>(b)), C()
{}
template<typename... Args>
A(Args&&... args) : B(), C(std::forward<Args>(args)...)
{}
};
Question: if the first version causes collision, the last version (my final purpose) its clear that it doesn't work also. How could I achieve this goal?

A possible solution would be use std::enable_if with std::is_convertible to only include the first constructor if the type of argument b is convertible to B:
template <
class fw_B,
class = typename std::enable_if<std::is_convertible<fw_B, B>::value, T>::type>
A(fw_B&& b)
For example:
#include <iostream>
#include <type_traits>
struct B
{
B() {}
B(int) {}
};
struct C {};
struct A : B, C
{
template <
class T,
class = typename std::enable_if<std::is_convertible<T, B>::value, T>::type>
A(T&& t) { std::cout << "A(T&&)\n"; }
template <class... TArgs>
A(TArgs&&... targs) { std::cout << "A(TArgs&&)\n"; }
};
int main()
{
B b;
A a1(b);
A a2(4);
A a3("hello");
return 0;
}
Output:
A(T&&)
A(T&&)
A(TArgs&&)
See demo at http://ideone.com/xJEjic .

Related

Conditional class template constructor

I am trying to make a class that has conditional members as below (sample code to illustrate problem):
template<bool b>
struct conditional_members {};
template<>
struct conditional_members<true>
{ int m; };
template<typename T, bool b>
struct my_class : public conditional_members<b>
{
T n;
// constructor for case when b is false
my_class(T n) : n(n) {};
// constructor for case when b is true
my_class(T n, int m) : n(n), m(m) {};
};
I need to have two conditional constructors depending on the bool b but this does not compile. I tried specializing the constructors with bool value:
template<typename T>
my_class<T, true>::my_class(T n, int m) : n(n), m(m) {};
template<typename T>
my_class<T, false>::my_class(T n) : n(n) {};
but that doesn't compile either because partial function template specializations are not allowed.
Is there a way to achieve this?
The problem with
// constructor for case when b is true
my_class(T n, int m) : n(n), m(m) {};
is that a constructor's mem-initializer-list can name only virtual base classes, direct base classes, and direct non-static data members, but never an inherited member like m. This is because the member of a base class is initialized by the base class subobject constructor, so it can't be initialized again (though it could be assigned).
You can instead specify the base class initializer. With this example, conditional_members is an aggregate, so aggregate initialization will work:
// constructor for case when b is true
my_class(T n, int m) : n(n), conditional_members<b>{m} {};
Though with just that, you might get some strange side effects from the fact that my_class specializations always have the two constructors declared, even if it might be invalid to actually instantiate one constructor or the other.
Here's an SFINAE trick to make the constructors conditionally effectively invisible, depending on b:
#include <type_traits>
// Define conditional_members as before.
template<typename T, bool b>
class my_class : public conditional_members<b>
{
T n;
public:
// constructor for case when b is false
template <typename = std::enable_if_t<!b>>
my_class(T n) : n(n) {}
// constructor for case when b is true
template <typename = std::enable_if_t<b>>
my_class(T n, int m) : conditional_members<b>{m}, n(n) {}
};
As a preview, with C++20 constraints, you'll be able to write it this nice, simpler way instead:
template<typename T, bool b>
class my_class : public conditional_members<b>
{
T n;
public:
// constructor for case when b is false
my_class(T n) requires(!b) : n(n) {}
// constructor for case when b is true
my_class(T n, int m) requires(b) : conditional_members<b>{m}, n(n) {}
};

Multiple inheritance of N classes with template [duplicate]

I have a diamond inheritance scheme, where the last child should be able to inherit from many different parents.
A
/|\
/ | \
B C ...
| | |
* *
D E
Now imagine I have a class D : public B, class E : public B, public C, etc. From D I want to call the same function of all its parents, which I am guaranteed exists due to the inheritance. My thought was that I could wrap this in some variadic template.
Currently I have this:
template <typename T>
class A
{
public:
A(T t) : mT(t) {}
virtual ~A() {}
virtual void doThings() = 0;
protected:
T mT;
};
template <typename T, typename A = A<T>>
class B : public A
{
public:
B(T t) : A(t) {}
virtual ~B() {}
virtual void doThings() { std::cout << "B" << std::endl; }
};
template <typename T, typename A = A<T>>
class C : public A
{
public:
C(T t) : A(t) {}
virtual ~C() {}
virtual void doThings() { std::cout << "C" << std::endl; }
};
Now I thought I could do something like this, which obviously does not work:
template <typename T, typename ...Args>
class ChildGenerator : public Args...
{
public:
ChildGenerator(T t) : Args(t)... {}
// The unpacking of the variadic template does not work here.
// Do I need to make it recursive somehow? How can I do that without having to instantiate new classes B and C?
void doThings() override { Args...::doThings();}
};
My hope is that I can use it like so:
int main()
{
using B = B<double>;
using C = C<double>;
B c1(0.0);
C c2(1.0);
ChildGenerator<double, B, C> c3(2.0);
c1.doThings();
c2.doThings();
c3.doThings();
}
Expected output (order does not matter):
B
C
B // <-- order of these two does not matter
C // <--
Is what I'm trying to achieve possible?
One way to iterate over the variadic bases:
template <typename T, typename ...Args>
class ChildGenerator : public Args...
{
public:
ChildGenerator(T t) : Args(t)... {}
void doThings() override {
int dummy[] = {0, (Args::doThings(), void(), 0)...};
static_cast<void>(dummy); // avoid warning for unused variable
}
};
or in C++17, with folding expression:
void doThings() override {
(static_cast<void>(Args::doThings()), ...);
}
Use a fold-expression (C++17):
void doThings() override { ((Args::doThings()) , ...);}
Live demo

Multiple inheritance with variadic templates: how to call function for each base class?

I have a diamond inheritance scheme, where the last child should be able to inherit from many different parents.
A
/|\
/ | \
B C ...
| | |
* *
D E
Now imagine I have a class D : public B, class E : public B, public C, etc. From D I want to call the same function of all its parents, which I am guaranteed exists due to the inheritance. My thought was that I could wrap this in some variadic template.
Currently I have this:
template <typename T>
class A
{
public:
A(T t) : mT(t) {}
virtual ~A() {}
virtual void doThings() = 0;
protected:
T mT;
};
template <typename T, typename A = A<T>>
class B : public A
{
public:
B(T t) : A(t) {}
virtual ~B() {}
virtual void doThings() { std::cout << "B" << std::endl; }
};
template <typename T, typename A = A<T>>
class C : public A
{
public:
C(T t) : A(t) {}
virtual ~C() {}
virtual void doThings() { std::cout << "C" << std::endl; }
};
Now I thought I could do something like this, which obviously does not work:
template <typename T, typename ...Args>
class ChildGenerator : public Args...
{
public:
ChildGenerator(T t) : Args(t)... {}
// The unpacking of the variadic template does not work here.
// Do I need to make it recursive somehow? How can I do that without having to instantiate new classes B and C?
void doThings() override { Args...::doThings();}
};
My hope is that I can use it like so:
int main()
{
using B = B<double>;
using C = C<double>;
B c1(0.0);
C c2(1.0);
ChildGenerator<double, B, C> c3(2.0);
c1.doThings();
c2.doThings();
c3.doThings();
}
Expected output (order does not matter):
B
C
B // <-- order of these two does not matter
C // <--
Is what I'm trying to achieve possible?
One way to iterate over the variadic bases:
template <typename T, typename ...Args>
class ChildGenerator : public Args...
{
public:
ChildGenerator(T t) : Args(t)... {}
void doThings() override {
int dummy[] = {0, (Args::doThings(), void(), 0)...};
static_cast<void>(dummy); // avoid warning for unused variable
}
};
or in C++17, with folding expression:
void doThings() override {
(static_cast<void>(Args::doThings()), ...);
}
Use a fold-expression (C++17):
void doThings() override { ((Args::doThings()) , ...);}
Live demo

constexpr non-static members for classes. Are they really compile time?

Consider a class with constexpr non static member function.
template <int k> class A { A() {} };
template <> class B : public A <k> {
B() : A{} {}
constexpr int foo() const { return k+42; }
}
Is foo() really compile time with any object of B? What about constexpr members?
template <int k> class A { A() {} };
template <> class B : public A <k> {
B() : A{} {}
constexpr int foo_var = k+42;
}
Will accesses to foo_var be compile time substituted? Will B have foo_var in its object memory layout?
What about std::array<T,N>::size()??

Initialize base subobject with dependent type name in derived class

Given this sample code with class C deriving from A or B depending on policy
#include <iostream>
#include <type_traits>
struct A
{
A(int a) { std::cout << a << "\n"; }
};
struct B
{
B(int a) { std::cout << -a << "\n"; }
};
template<bool>
struct policy;
template<>
struct policy<true> { typedef A type; };
template<>
struct policy<false> { typedef B type; };
template<typename T>
struct C : public policy<std::is_polymorphic<T>::value>::type
{
C() : /* ????? */(5) {}
};
int main()
{
C<int> a; // should print -5
C<std::ostream> b; // should print 5
}
How do I initialize the base class of C? (or, if it's not possible, is there a workaround?)
Do it just the way you found the base class of C:
template<typename T>
struct C : public policy<std::is_polymorphic<T>::value>::type
{
C() : policy<std::is_polymorphic<T>::value>::type(5) {}
};
Of course, to make it more readable, you can also add a typedef (maybe you will need the base class multiple times within C, then it's worth it). This would look like this:
template<typename T>
struct C : public policy<std::is_polymorphic<T>::value>::type
{
typedef typename policy<std::is_polymorphic<T>::value>::type Base;
C() : Base(5) {}
};
To make it a little less ugly, you could also add another layer of indirection, e.g. a template class BaseForC that yields the correct base as BaseForC<T>::type and encapsulates what policy and is_polymorphic are doing now into one class.
Here's a lazy solution:
template <typename T,
typename Base = typename std::conditional<
std::is_polymorphic<T>::value, A, B>::type>
struct C : Base
{
C() : Base(5) {}
};
The has the cost of giving your template C a different signature, and people might abuse that.