Можно ли извлечь тип различенного объединения для инициализации «автоматической» переменной? Достаточно просто, если вы передаете тип в шаблон, но я бы хотел что-то «авто». Было бы здорово использовать решение с использованием функции посетителя или ограниченного списка типов (например, mpl :: vector).
Пример показан ниже:
#include <iostream>
#include <typeindex>
#include <cassert>
struct d_union {
template <typename T>
d_union(T t) {
*reinterpret_cast<T*>(data) = t;
_type_id = &typeid(T);
}
template <typename T>
const T* get_pointer() const {
if (_type_id == &typeid(T))
return reinterpret_cast<const T*>(data);
else
return nullptr;
}
template <typename T>
const T get() const {
assert (_type_id == &typeid(T));
return *get_pointer<T>();
}
alignas(8) char data[8];
const std::type_info *_type_id;
};std::ostream& operator<<(std::ostream&os, const d_union &u) {
if (auto ip = u.get_pointer<int>())
os << *ip;
if (auto fp = u.get_pointer<float>())
os << *fp;
return os;
}
int main() {
d_union _i = d_union(42);
d_union _f = d_union(3.14f);
std::cout << "d_union(42) = " << _i << std::endl;
std::cout << "d_union(3.14) = " << _f << std::endl;
int _get_i = _i.get<int>();
std::cout << "d_union(42).get<int>() = " << _get_i << std::endl;
// auto _get_auto = _i.get();
// std::cout << "d_union(42).get()" << _get_auto << std::endl;
}
Любые возможные решения будут оценены!
Спасибо
Вы ищете Boost.TypeErasure библиотека. Это позволит вам транслировать любой поток естественным образом. Из учебника:
any<
mpl::vector<
copy_constructible<>,
typeid_<>,
incrementable<>,
ostreamable<>
>
> x(10);
++x;
std::cout << x << std::endl; // prints 11
x
здесь может быть любой тип, который удовлетворяет данным понятиям.
Если это не совсем то, что вам нужно, тогда в Boost также есть библиотека различного объединения Variant, которая имеет интерфейс для посетителей.
Как правило, когда вы переопределяете глобальные операторы потока для пользовательского типа класса, вы должны реализовать их в терминах вызовов методов-членов и позволить классу решать, как выполнять потоковую передачу, например:
struct d_union {
...
void outputTo(std::ostream &os) const {
if (auto ip = get_pointer<int>())
os << *ip;
else if (auto fp = get_pointer<float>())
os << *fp;
...
}
...
};
std::ostream& operator<<(std::ostream &os, const d_union &u) {
u.outputTo(os);
return os;
}
Это, как говорится, если вы хотите что-то немного больше «авто» когда operator<<
вызывается, может быть, вы могли бы попробовать что-то вроде этого (не идеально, но близко к тому, что вы ищете, учитывая d_union
не знает, что он держит до времени выполнения, и если вы добавили operator=
тогда он может даже динамически менять тип)
typedef void (*pOutputProc)(const d_union&, std::ostream&);
template <typename T>
void outputProc(const d_union &u, std::ostream &os)
{
os << *(u.get_pointer<T>());
}
std::unordered_map<std::type_index, pOutputProc> outputProcs;
template <typename T>
void registerOutputProc()
{
outputProcs[std::type_index(typeid(T))] = &outputProc<T>;
}
void registerOutputProcs()
{
registerOutputProc<int>();
registerOutputProc<float>();
...
}
#pragma startup registerOutputProcs
struct d_union {
...
void outputTo(std::ostream &os) const {
pOutputProc proc = outputProcs[std::type_index(*_type_id)];
if (proc) proc(*this, os);
}
...
};
std::ostream& operator<<(std::ostream &os, const d_union &u) {
u.outputTo(os);
return os;
}
Тогда вам просто нужно будет заселить registerOutputProcs()
с различными типами данных, которые вы хотите d_union
поддерживать.
В общем, это невозможно, поскольку C ++ не является языком с динамической типизацией.
В определенных случаях это будет необходимо для (в вашем случае) operator<<()
изучить type_info
и делать вещи в зависимости от того, какой тип на самом деле там. Ограничением является то, что необходимо жестко закодировать знание того, какие типы могут храниться в вашем struct
— если вы хотите добавить поддержку для разных типов, необходимо будет добавить код и перестроить вашу программу.
auto
полагается на то, что компилятор знает тип во время компиляции. type_info
получает значения во время выполнения.