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

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()??

Related

How to inherit same class multiple times?

Is it possible to inherit kind of two same classes like this? I was able to compile this on msvc, but failed to compile on g++/clang++. I'm getting error:
Source.cpp:14:12: warning: direct base 'a' is inaccessible due to ambiguity:
struct b -> struct a
struct b -> class_combiner<struct a> -> struct a [-Winaccessible-base]
struct b : public a, public class_combiner<a> {
^~~~~~~~
Source.cpp:17:12: error: ambiguous conversion from derived class 'b' to base class 'a':
struct b -> struct a
struct b -> class_combiner<struct a> -> struct a
a::f();
Source:
template <typename T>
struct class_combiner : public T {
using T::T;
};
struct a {
void f() {}
};
struct b : public a, public class_combiner<a> {
void f2() {
a::f();
b::class_combiner::f();
}
};
int main() {
b x;
x.f2();
}
Doable quick fix I came up with:
template <typename T, unsigned int instance>
struct class_combiner : public T {
using T::T;
};
struct a {
void f() {}
};
struct b : public class_combiner<a, 0>, public class_combiner<a, 1> {
void f2() {
class_combiner<a, 0>::f();
class_combiner<a, 1>::f();
}
};
int main() {
b x;
x.f2();
}

How do I call generic variable's method when I specify T must be based of some class in C++?

class Base {
public:
void A() {}
};
class Derived: public Base {
public:
void B() {}
};
template <typename T, std::enable_if<std::is_base_of<Base, T>::value, int>::type = 0>
class SomeClass {
public:
T t;
// I want to call method A() with variable 't'.
void invoke() { t.A(); }
};
auto some = new someClass<Derived>();
// I want to call method B() when the 'T' specify to 'Derived'.
some->t.B();
How do I call the A() method when the 'T' must be based of class 'Base', and call the B() method when the 'T' in the class 'someClass' specify to 'Derived'?
You can specialise a template.
template<typename>
class SomeClass;
template<>
class SomeClass<Base>
{
public:
Base t;
void invoke() { t.A(); }
}
template<>
class SomeClass<Derived>
{
public:
Derived t;
void invoke() { t.B(); }
}

Public inheritance of a class template fails unexpectedly

Why does the following fail with error: 'a_' was not declared in this scope in the context of Bar::get()?
template <typename N>
class Foo
{
public:
Foo() { }
protected:
N a_;
};
template <typename N>
class Bar : public Foo<N>
{
public:
Bar() : Foo<N>() { }
N get() { return a_; }
};
You need to use the reference this->_a
N get() { return this->a_; }

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

How to create special words

I'm trying to build a templat-class A and call its default constructor via a special word "NONE.
consider I have:
template<class T>
class A {
public:
A():_val(0);
A(T val):_val(val);
private:
int _val;
}
and I want to be able to write
A<int> x = None;
which will call A();
I was thinking maybe I can use some sort of typedef, but I don't know how
You could provide a dummy type and a constructor that takes that type and does the equivalent of default constructing an instance. For example,
struct None_t {};
constexpr None_t None{}; // const None_t None = {}; in C++03
template<class T>
class A {
public:
A() : _val() {};
A(None_t) : A() {} // A(None_t) : _val() {} in C++03
A(T val) : _val(val) {}
private:
T _val;
};
int main()
{
A<int> x = None;
}
Note I changed _val to from int to T, since otherwise the template doesn't make much sense.
The usual way would be to create a tag class, in this case none_type and have a constexpr (or static const) model of it available.
struct none_type {};
constexpr auto none = none_type {};
template<class T>
class A {
public:
A():_val(0) {};
A(none_type) : A() {};
A(int val):_val(val) {};
private:
int _val;
};
int main()
{
A<int> a = none;
}