我想知道一种可能的方法来使类的内存布局在模板化代码中更有效。据我所知,标准要求类的数据成员按照声明的顺序排列在内存中。编译器可能会进行填充以对齐数据成员,从而不必要地增加类的大小。这个想法是在编译时重新排列数据成员声明以最小化这种填充。我做了一些搜索,但找不到任何信息(大多数时候人们讨论打包编译器指令,这与我看到的不太一样)。
首先,请考虑以下(琐碎但重复且丑陋的)代码(ideone.com 上的相同代码)(问题在代码下方,请随意跳至它们):
#include <iostream>
#include <cstdint>
namespace so
{
template <typename Ta, typename Tb, typename Tc, std::size_t =
((sizeof(Ta) >= sizeof(Tb)) && (sizeof(Tb) >= sizeof(Tc))) ? 10 :
((sizeof(Ta) >= sizeof(Tc)) && (sizeof(Tc) >= sizeof(Tb))) ? 11 :
((sizeof(Tb) >= sizeof(Ta)) && (sizeof(Ta) >= sizeof(Tc))) ? 20 :
((sizeof(Tb) >= sizeof(Tc)) && (sizeof(Tc) >= sizeof(Ta))) ? 21 :
((sizeof(Tc) >= sizeof(Ta)) && (sizeof(Ta) >= sizeof(Tb))) ? 30 :
((sizeof(Tc) >= sizeof(Tb)) && (sizeof(Tb) >= sizeof(Ta))) ? 31 : 0>
struct foo {};
template <typename Ta, typename Tb, typename Tc>
struct foo<Ta, Tb, Tc, 10>
{
Ta a;
Tb b;
Tc c;
foo(Ta _a, Tb _b, Tc _c) : a{_a}, b{_b}, c{_c} {}
};
template <typename Ta, typename Tb, typename Tc>
struct foo<Ta, Tb, Tc, 11>
{
Ta a;
Tc c;
Tb b;
foo(Ta _a, Tb _b, Tc _c) : a{_a}, c{_c}, b{_b} {}
};
template <typename Ta, typename Tb, typename Tc>
struct foo<Ta, Tb, Tc, 20>
{
Tb b;
Ta a;
Tc c;
foo(Ta _a, Tb _b, Tc _c) : b{_b}, a{_a}, c{_c} {}
};
template <typename Ta, typename Tb, typename Tc>
struct foo<Ta, Tb, Tc, 21>
{
Tb b;
Tc c;
Ta a;
foo(Ta _a, Tb _b, Tc _c) : b{_b}, c{_c}, a{_a} {}
};
template <typename Ta, typename Tb, typename Tc>
struct foo<Ta, Tb, Tc, 30>
{
Tc c;
Ta a;
Tb b;
foo(Ta _a, Tb _b, Tc _c) : c{_c}, a{_a}, b{_b} {}
};
template <typename Ta, typename Tb, typename Tc>
struct foo<Ta, Tb, Tc, 31>
{
Tc c;
Tb b;
Ta a;
foo(Ta _a, Tb _b, Tc _c) : c{_c}, b{_b}, a{_a} {}
};
template <typename Ta, typename Tb, typename Tc>
struct bar: public foo<Ta, Tb, Tc>
{
private:
using base = foo<Ta, Tb, Tc>;
public:
bar() = default;
using base::base;
};
template <typename Ta, typename Tb, typename Tc>
struct foobar
{
Ta a;
Tb b;
Tc c;
foobar() = default;
foobar(Ta _a, Tb _b, Tc _c) : a{_a}, b{_b}, c{_c} {}
};
} //namespace so
int main()
{
so::bar<std::uint16_t, std::uint32_t, std::uint16_t> bar{1, 2, 3};
so::foobar<std::uint16_t, std::uint32_t, std::uint16_t> foobar{1, 2, 3};
std::cout << sizeof(bar) << "\t" << sizeof(foobar) << std::endl;
std::cout << bar.a << " : " << bar.b << " : " << bar.c << std::endl;
std::cout << foobar.a << " : " << foobar.b << " : " << foobar.c << std::endl;
return (0);
}
程序输出:
8 12
1 : 2 : 3
1 : 2 : 3
问题:
- 是否有一些众所周知的、独立于编译器的方法来解决此类问题(也许是 Boost)?
- 如果不是,是否有一些特定于编译器的指令会自动执行此类操作(没有 GCC 的数据错位
__atribute__((packed))
)? - 这可以以更通用的方式完成(可能使用可变参数模板)吗?
提前致谢!