我想重寫std::variant
的基礎,因爲我必須使用C++ 14編譯器(不含std :: variant),而且我需要類型安全枚舉。執行變體時破壞錯誤
我的代碼只能與基本類型的作品(即int
,float
,char *
等),但使用std::string
例如當我有破壞的問題。
這裏是我的代碼:
namespace utils
{
namespace // private implementation
{
template<std::size_t Index, typename T, typename... Rest>
struct can_construct_type : std::false_type {}; // End of recursion, T is not in Rest...
template<std::size_t Index, typename T, typename First>
struct can_construct_type<Index, T, First> : std::is_constructible<First, T>
{ // There is only one type remaining to check
static constexpr std::size_t index = Index;
};
template<std::size_t Index, typename T, typename First, typename... Rest>
struct can_construct_type<Index, T, First, Rest...> : std::integral_constant<bool, std::is_constructible<First, T>::value || can_construct_type<Index + 1, T, Rest...>::value>
{ // Main recursive loop. Check for First, then recursively for Rest...
static constexpr std::size_t index = (std::is_constructible<First, T>::value ? Index : can_construct_type<Index + 1, T, Rest...>::index);
};
}
template<typename T, typename... Types>
using can_construct_type = can_construct_type<0, T, Types...>;
}
template<typename... Types>
class variant
{
template<typename _Vp> friend void * __get_storage(_Vp &);
using storage_t = std::aligned_union_t<0u, Types...>;
storage_t m_storage;
int m_type_index;
/* creation of content */
template<typename T> inline void set_value(T const & value)
{
new ((T *)std::addressof(m_storage)) T(value);
m_type_index = utils::can_construct_type<T, Types...>::index;
}
/* destruction of content */
inline void destroy_data(void) { invoke_destructor(m_type_index, std::addressof(m_storage)); }
static void invoke_destructor(int type, storage_t * storage_address)
{
static const std::array<void(*)(storage_t *), sizeof...(Types)> destructors
{
std::addressof(invoke_destructor_impl<Types>)...
};
destructors[type](storage_address);
}
template<class T> static void invoke_destructor_impl(storage_t * storage_address)
{
T * pt = reinterpret_cast<T *>(storage_address);
delete pt;
//pt->~T(); // I tried delete or ->~T() but both crash
}
public:
variant() = delete;
template<typename T> variant(T value)
{
set_value(value);
}
template<typename T> variant & operator=(T & value)
{
destroy_data();
set_value(value);
return *this;
}
~variant()
{
destroy_data();
}
std::size_t index(void) const
{
return m_type_index;
}
};
/* getter */
template<typename Variant> static void * __get_storage(Variant & var)
{
return reinterpret_cast<void *>(std::addressof(var.m_storage));
}
template<typename T, typename... Types> T * get_if(variant<Types...> & var)
{
return (var.index() == utils::contains_type<T, Types...>::index
? reinterpret_cast<T *>(__get_storage(var))
: nullptr);
}
/* tests */
int main()
{
variant<int, char *> var_test(42);
int * value1 = get_if<int>(var_test);
if (value1)
{
std::cout << *value1 << "\n"; // OK
}
var_test = _strdup("Hello !");
char ** value2 = get_if<char *>(var_test);
if (value2)
{
std::cout << *value2 << "\n"; // OK
}
variant<int, std::string> var_test_2(42);
//var_test_2 = _strdup("Hello again !");
var_test_2 = std::string("Hello again !");
std::string * value3 = get_if<std::string>(var_test_2);
if (value3)
{
std::cout << *value3 << "\n";
}
return 0; // it crashes when the destructor of var_test_2 is called
}
我把一個完整的代碼示例,但只有variant
實現是非常重要的。
我想我嚴重使用std::aligned_union
,但我不知道在哪裏以及如何。
我得到的錯誤:
Exception thrown at 0x00096370 in Test.exe: 0xC0000005: Access violation writing location 0xDDDDDDDD.
更新:似乎調用析構函數兩次,但我沒有找到原因。
你的「破壞問題」是什麼? – Carcigenicate
@Carcigenicate更新 – Boiethios
>我想重寫std :: variant的基礎,因爲我必須使用C++ 14編譯器: 使用boost :: variant? –