patterncppMinor
Movable and copyable variant
Viewed 0 times
andvariantcopyablemovable
Problem
What do you think about this variant class?
Some hype: no RTTI needed, no heap allocation, supports copying.
```
#pragma once
#ifndef VARIANT_HPP
# define VARIANT_HPP
#include
#include
#include
#include
#include
namespace detail
{
template
struct max_align_type
{
using type = typename ::std::conditional alignof(typename max_align_type::type)),
A,
typename max_align_type::type
>::type;
};
template
struct max_align_type
{
using type = typename ::std::conditional alignof(B)), A, B>::type;
};
template
struct max_align_type
{
using type = A;
};
template
struct max_size_type
{
using type = typename ::std::conditional sizeof(typename max_size_type::type)),
A,
typename max_size_type::type
>::type;
};
template
struct max_size_type
{
using type = typename ::std::conditional sizeof(B)), A, B>::type;
};
template
struct max_size_type
{
using type = A;
};
template
struct index_of :
::std::integral_constant{} ?
0 :
(-1 == index_of{}) ? -1 : 1 + index_of{}
>
{
};
template
struct index_of :
::std::integral_constant{} - 1>
{
};
template
struct has_duplicates :
::std::integral_constant{} ? has_duplicates{} : true)
>
{
};
template
struct has_duplicates :
::std::integral_constant
{
};
template
struct compatible_index_of :
::std::integral_constant{} ?
0 :
(-1 == compatible_index_of{}) ?
-1 :
1 + compatible_index_of{}
>
{
};
template
struct compatible_index_of :
::std::integral_constant{} - 1>
{
};
template
struct compatible_type
{
using type = typename ::std::conditional{},
B,
typename compatible_type::type
>::type;
};
template
struct compatible_type
{
using type = typename ::std::conditional{}, B, void>::type;
};
template
struct is_streamable : ::std::false_type { };
template
struct is_streamable()
()))))
> : ::std::true_type
{
};
template
struct type_at : type_at
{
};
template
struct type_at
{
using type = A;
};
template
using
Some hype: no RTTI needed, no heap allocation, supports copying.
```
#pragma once
#ifndef VARIANT_HPP
# define VARIANT_HPP
#include
#include
#include
#include
#include
namespace detail
{
template
struct max_align_type
{
using type = typename ::std::conditional alignof(typename max_align_type::type)),
A,
typename max_align_type::type
>::type;
};
template
struct max_align_type
{
using type = typename ::std::conditional alignof(B)), A, B>::type;
};
template
struct max_align_type
{
using type = A;
};
template
struct max_size_type
{
using type = typename ::std::conditional sizeof(typename max_size_type::type)),
A,
typename max_size_type::type
>::type;
};
template
struct max_size_type
{
using type = typename ::std::conditional sizeof(B)), A, B>::type;
};
template
struct max_size_type
{
using type = A;
};
template
struct index_of :
::std::integral_constant{} ?
0 :
(-1 == index_of{}) ? -1 : 1 + index_of{}
>
{
};
template
struct index_of :
::std::integral_constant{} - 1>
{
};
template
struct has_duplicates :
::std::integral_constant{} ? has_duplicates{} : true)
>
{
};
template
struct has_duplicates :
::std::integral_constant
{
};
template
struct compatible_index_of :
::std::integral_constant{} ?
0 :
(-1 == compatible_index_of{}) ?
-1 :
1 + compatible_index_of{}
>
{
};
template
struct compatible_index_of :
::std::integral_constant{} - 1>
{
};
template
struct compatible_type
{
using type = typename ::std::conditional{},
B,
typename compatible_type::type
>::type;
};
template
struct compatible_type
{
using type = typename ::std::conditional{}, B, void>::type;
};
template
struct is_streamable : ::std::false_type { };
template
struct is_streamable()
()))))
> : ::std::true_type
{
};
template
struct type_at : type_at
{
};
template
struct type_at
{
using type = A;
};
template
using
Solution
I can think of one small improvement you can make.
In the assignment operator (for both
Otherwise, this is a pretty cool class -- always interesting to see what's possible with C++, though I'd have to see a fairly deep series of unit tests to be fully confident this code is correct. Some ideas for test cases:
Some of these are a bit paranoid, but this is certainly the type of class where I'd like to push into the corner cases to ensure that they work as I expect.
In the assignment operator (for both
variant and U arguments), if the typeid of the argument is the same as store_type_, you can move the argument directly into store instead of deleting and re-newing.Otherwise, this is a pretty cool class -- always interesting to see what's possible with C++, though I'd have to see a fairly deep series of unit tests to be fully confident this code is correct. Some ideas for test cases:
std::unique_ptrwith custom deleters moved into avariant
- types with different alignments stored in the same
variant
variants stored in avariant
- trying to store a non-movable type fails to compile
- Simple things, like
getfails to compile ifUisn't one of the types (e.g. if it's a subtype of one of the types)
getthrows whenUisn't currently stored
containsworks correctly
variant v(Foo()); Foo foo = std::move(v.get());works correctly.
Some of these are a bit paranoid, but this is certainly the type of class where I'd like to push into the corner cases to ensure that they work as I expect.
Context
StackExchange Code Review Q#28939, answer score: 4
Revisions (0)
No revisions yet.