The following code contains an example template X
, where the data-member is unused, if the template is parametrized with other type than A
. But the sizes of the objects a
and b
are the same, even with -O3
, so the optimizer does not remove the unused data-member x2
.
#include <iostream>
#include <cstdint>
#include <type_traits>
struct A {};
struct B {};
template<typename T>
struct X {
int value() const {
if constexpr(std::is_same_v<T, A>) {
return x1 + x2;
}
else {
return x1;
}
}
private:
int x1{0};
int x2{0};
};
int main() {
X<A> a;
X<B> b;
std::cout << sizeof(a) << '\n';
std::cout << sizeof(b) << '\n';
return a.value() + b.value();
}
Now there are two questions:
- Is the optimizer not allowed (
as-if
-rule) to remove the unused data-member? Why? - How to achieve the goal: that the class
X<B>
does not contain the unused data-memberx2
?
There is a workaround with a base-class template and a specialisation for A
that contains the data-member x2
. But this solution is cumbersome. I wonder if there is a solution without using a base class?
Edit:
I don't think that using the sizeof()
operator prevents the optimization:
//#include <iostream>
#include <cstdint>
#include <type_traits>
struct A {};
struct B {};
template<typename T>
struct X {
int value() const {
if constexpr(std::is_same_v<T, A>) {
return x1 + x2;
}
else {
return x1;
}
}
private:
int x1{0};
int x2{1};
};
X<A> a;
X<B> b;
int main() {
// std::cout << sizeof(a) << '\n';
// std::cout << sizeof(b) << '\n';
return a.value() + b.value();
}
If you look a the assembly (e.g. compiler explorer) you see that the instances contain in both cases both data-members.