Die erste Klasse wird für private Vererbung verwendet, um das exakt gleiche Layout zu gewährleisten. Dies sollte Casting sicher machen.Ist es sicher, in eine Klasse zu konvertieren, die dasselbe Datenelementlayout aufweist, aber eine andere Implementierung?
#include <iostream>
#include <string>
struct data_base
{
data_base(int i, std::string&& s) noexcept
: i_{ i }
, s_{ std::move(s) }
{}
int i_;
std::string s_;
};
In diesem trivialen Beispiel drucke ich das int
Datenelement zuerst durch das std::string
Daten Mitglied gefolgt von Instanzen von data<true>
.
template<bool = true>
struct data : private data_base // inherits
{
data(int i, std::string&& s) noexcept
: data_base(i, std::move(s))
{}
void print()
{
std::cout << "data<true> - " << i_ << s_ << '\n';
}
};
jedoch die data<false>
druckt das std::string
Datenelement zunächst durch das int
Daten Mitglied gefolgt.
template<>
struct data<false> : private data_base
{
void print()
{
std::cout << "data<false> - " << s_ << i_ << '\n';
}
};
Beispiel:
int main()
{
data<true> d{ 5, "abc" };
d.print();
((data<false>&)d).print();
}
Demo: http://coliru.stacked-crooked.com/a/8b1262afe23dc0a2
Als die Demo zeigt, auch mit der -fstrict-aliasing
Fahne, es gibt keine Warnungen ist.
Jetzt, da sie das gleiche Layout haben, dachte ich, dass ich einfach zwischen den beiden Typen umwandeln könnte, um eine andere Art von statischem Polymorphismus zu bekommen; ohne die Kosten eines virtuellen Funktionsaufrufs.
Ist diese Verwendung sicher oder löst ich ein undefiniertes Verhalten aus?
Nicht sicher, ob 'std :: string' garantiert eine Standardlayout-Klasse ist –
Ich denke, der 'print' Aufruf zählt als" Verwendung des gespeicherten Wertes "für die Zwecke der strengen Aliasing-Regel, aber nicht 100% sicher –
Jede Umwandlung zwischen nicht verwandten Typen verursacht genaugenommen undefiniertes Verhalten. Außerdem wird in C++ empfohlen, die C++ - Cast-Operatoren anstelle von C-artigen Umwandlungen zu verwenden. – antred