Coder Social home page Coder Social logo

mpark / variant Goto Github PK

View Code? Open in Web Editor NEW
660.0 660.0 88.0 34.65 MB

C++17 `std::variant` for C++11/14/17

Home Page: https://mpark.github.io/variant

License: Boost Software License 1.0

CMake 4.57% C++ 89.90% Shell 0.56% Python 4.97%
cpp cpp11 cpp14 cpp17 cpp20 discriminated-unions polymorphism variant

variant's People

Contributors

ax3l avatar elelel avatar gridley avatar marektamaskovic avatar mpark avatar sbolding-lanl avatar sieren avatar tcbrindle avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

variant's Issues

Fails to compile with MSVC 19.15

Microsoft managed to break the successful compilation of the variant sources again. The latest update of MS Visual Studio 2017 (version 15.8, MSVC 19.15) produces messages like these:

vartest.cpp(935): error C2131: expression did not evaluate to a constant
vartest.cpp(935): note: failure was caused by a read of a variable outside its lifetime
vartest.cpp(935): note: see usage of '<traits_0>'
vartest.cpp(1754): note: see reference to class template instantiation 'mpark::detail::traits<int>' being compiled
vartest.cpp(2053): note: see reference to class template instantiation 'mpark::detail::impl<int>' being compiled
vartest.cpp(2460): note: see reference to class template instantiation 'mpark::variant<int>' being compiled
vartest.cpp(963): error C2131: expression did not evaluate to a constant
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.15.26726\include\initializer_list(42): note: failure was caused by non-constant arguments or reference to a non-constant symbol
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.15.26726\include\initializer_list(42): note: see usage of '$S3'
vartest.cpp(968): error C2131: expression did not evaluate to a constant
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.15.26726\include\initializer_list(42): note: failure was caused by non-constant arguments or reference to a non-constant symbol
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.15.26726\include\initializer_list(42): note: see usage of '$S5'
vartest.cpp(973): error C2131: expression did not evaluate to a constant
vartest.cpp(973): note: failure was caused by a read of an uninitialized symbol
vartest.cpp(973): note: see usage of 'copy_constructible_trait'
vartest.cpp(979): error C2131: expression did not evaluate to a constant
vartest.cpp(979): note: failure was caused by a read of an uninitialized symbol
vartest.cpp(979): note: see usage of 'move_constructible_trait'
vartest.cpp(985): error C2131: expression did not evaluate to a constant
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.15.26726\include\initializer_list(42): note: failure was caused by non-constant arguments or reference to a non-constant symbol
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.15.26726\include\initializer_list(42): note: see usage of '$S7'
vartest.cpp(1754): error C2975: 'unnamed-parameter': invalid template argument for 'mpark::detail::copy_assignment', expected compile-time constant expression
vartest.cpp(1716): note: see declaration of 'unnamed-parameter'
vartest.cpp(1754): error C2440: 'specialization': cannot convert from 'int' to 'mpark::detail::Trait'
vartest.cpp(1754): note: Conversion to enumeration type requires an explicit cast (static_cast, C-style cast or function-style cast)
vartest.cpp(1738): error C2975: 'unnamed-parameter': invalid template argument for 'mpark::detail::move_assignment', expected compile-time constant expression
vartest.cpp(1676): note: see declaration of 'unnamed-parameter'
vartest.cpp(1754): note: see reference to class template instantiation 'mpark::detail::copy_assignment<mpark::detail::traits<int>,0>' being compiled
vartest.cpp(1738): error C2440: 'specialization': cannot convert from 'int' to 'mpark::detail::Trait'
vartest.cpp(1738): note: Conversion to enumeration type requires an explicit cast (static_cast, C-style cast or function-style cast)
vartest.cpp(1594): error C2975: 'unnamed-parameter': invalid template argument for 'mpark::detail::copy_constructor', expected compile-time constant expression
vartest.cpp(1556): note: see declaration of 'unnamed-parameter'
vartest.cpp(1698): note: see reference to class template instantiation 'mpark::detail::assignment<mpark::detail::traits<int>>' being compiled
vartest.cpp(1738): note: see reference to class template instantiation 'mpark::detail::move_assignment<mpark::detail::traits<int>,0>' being compiled
vartest.cpp(1594): error C2440: 'specialization': cannot convert from 'int' to 'mpark::detail::Trait'
vartest.cpp(1594): note: Conversion to enumeration type requires an explicit cast (static_cast, C-style cast or function-style cast)
vartest.cpp(1578): error C2975: 'unnamed-parameter': invalid template argument for 'mpark::detail::move_constructor', expected compile-time constant expression
vartest.cpp(1518): note: see declaration of 'unnamed-parameter'
vartest.cpp(1594): note: see reference to class template instantiation 'mpark::detail::copy_constructor<Traits,0>' being compiled
        with
        [
            Traits=mpark::detail::traits<int>
        ]
vartest.cpp(1578): error C2440: 'specialization': cannot convert from 'int' to 'mpark::detail::Trait'
vartest.cpp(1578): note: Conversion to enumeration type requires an explicit cast (static_cast, C-style cast or function-style cast)
vartest.cpp(1471): error C2975: 'unnamed-parameter': invalid template argument for 'mpark::detail::destructor', expected compile-time constant expression
vartest.cpp(1423): note: see declaration of 'unnamed-parameter'
vartest.cpp(1540): note: see reference to class template instantiation 'mpark::detail::constructor<mpark::detail::traits<int>>' being compiled
vartest.cpp(1578): note: see reference to class template instantiation 'mpark::detail::move_constructor<mpark::detail::traits<int>,0>' being compiled
vartest.cpp(1471): error C2440: 'specialization': cannot convert from 'int' to 'mpark::detail::Trait'
vartest.cpp(1471): note: Conversion to enumeration type requires an explicit cast (static_cast, C-style cast or function-style cast)
vartest.cpp(1472): error C2975: 'unnamed-parameter': invalid template argument for 'mpark::detail::destructor', expected compile-time constant expression
vartest.cpp(1423): note: see declaration of 'unnamed-parameter'
vartest.cpp(1472): error C2440: 'specialization': cannot convert from 'int' to 'mpark::detail::Trait'
vartest.cpp(1472): note: Conversion to enumeration type requires an explicit cast (static_cast, C-style cast or function-style cast)
vartest.cpp(1595): error C2975: 'unnamed-parameter': invalid template argument for 'mpark::detail::copy_constructor', expected compile-time constant expression
vartest.cpp(1556): note: see declaration of 'unnamed-parameter'
vartest.cpp(1595): error C2440: 'specialization': cannot convert from 'int' to 'mpark::detail::Trait'
vartest.cpp(1595): note: Conversion to enumeration type requires an explicit cast (static_cast, C-style cast or function-style cast)
vartest.cpp(1755): error C2975: 'unnamed-parameter': invalid template argument for 'mpark::detail::copy_assignment', expected compile-time constant expression
vartest.cpp(1716): note: see declaration of 'unnamed-parameter'
vartest.cpp(1755): error C2440: 'specialization': cannot convert from 'int' to 'mpark::detail::Trait'
vartest.cpp(1755): note: Conversion to enumeration type requires an explicit cast (static_cast, C-style cast or function-style cast)

Determine which functions should not throw and handle the corrupted state

Suppose variant<T, U> v; is corrupted. Should variant<T, U> w(v) throw a bad_variant_access exception? or should w simply also be corrupted?

Suppose variant<T, U> v, w; are both corrupted. Should swap(v, w) throw a bad_variant_access exception? or should it be a no-op?

The full list of operations that need to be considered:

  • copy/move constructor
  • copy/move assignment operator
  • hash
  • swap
  • relational operators

Support for pointers to incomplete types

First of all, thank you for providing this implementation of std::variant. It's great to have a lightweight alternative to boost::variant available in C++11.
I just stumbled over an issue with recursive type definitions, and I'm not sure whether it's a limitation of C++11 or the variant implementation. The following struct definition compiles fine with GCC's and Clang's C++17 support:

struct S {
    std::variant<
        std::map<int, S>*
    > var;
};

When replacing std::variant with mpark::variant, I get an error message regarding the incomplete type S of std::pair<int, S>::second. Is it possible to enhance your implementation so that this kind of recursive type definition compiles with mpark::variant under C++11 as well?

Add more constexpr tests

Specifically, a variant that contains references as alternatives are lacking constexpr tests.

Add support for compilation with exceptions disabled

If compiler support for exceptions is turned off, usually via -fno-exceptions command line switch on gcc/clang, then std::variant can never be in the valueless_by_exception state. Thus, you should then be able to call std::visit<>() or std::get<>() without them doing the test for empty or having them call throw.

As it stands now, you can't compile variant without having exception support enabled.

`static_assert` vs SFINAE

For type-based operations, there must be exactly one instance of T in the list of alternatives.
Determine whether this violation should be a static_assert within the function or a SFINAE + = delete;.

Behaviour when contained type has overload for unary operator &

Hi!

First of all, thanks for implementing this, great job!

I noticed that variant<> would not compile when I used a type with overloaded operator& as an alternative. access::get_if gave the following error:

'auto' in return type deduced as 'thing' here but deduced as 'wrapper' in earlier return statement.

wrapper<thing>::operator&, in my case, is returning thing *.

Changing get_if like this makes that part work:

 constexpr auto *get_if(Variant *v) {
   using V = decay_t<Variant>;
   static_assert(I < experimental::tuple_size<V>::value, "");
   using T = experimental::tuple_element_t<I, V>;
   assert(v);
   if (!holds_alternative<I>(*v)) {
     using R = add_pointer_t<lib::qualify_as_t<T, Variant>>;
     return static_cast<R>(nullptr);
   }  // if
-  return &unsafe::get<I>(*v);
+  return std::addressof(unsafe::get<I>(*v));
 }

I also had to change the UNION_IMPL macro like this to avoid some nasty crashes:

     template <typename... Args>                                                                              \
     void construct(lib::size_constant<0>, Args &&... args) {                                                 \
-      ::new (&head_) head(forward<Args>(args)...);                                                           \
+      ::new (std::addressof(head_)) head(forward<Args>(args)...);                                            \
     }                                                                                                        \

I am not sure about the changes above, but it seems to be what the standard wants: http://en.cppreference.com/w/cpp/utility/variant/get_if

It seems like std::addressof() does not become constexpr until C++17 though...

Cheers,
Erik

No longer works with Visual Studio 2017

I've just updated to VS 15.5 (toolset 14.12), and no longer able to build projects which use the variant.
Here're the errors (in case it helps):

C3528	'Is': the number of elements in this pack expansion does not match the number of elements in 'Js'	...\mpark\variant.hpp	575
C2672	'mpark::detail::visitation::base::make_farray': no matching overloaded function found	cvtest	...\mpark\variant.hpp	574
C2893	Failed to specialize function template 'mpark::lib::cpp14::array<std::common_type<std::decay<Fs>::type...>::type,sizeof...(Fs)> mpark::detail::visitation::base::make_farray(Fs &&...)'	...\mpark\variant.hpp	575
C2672	'mpark::detail::visitation::base::at': no matching overloaded function found	...\mpark\variant.hpp	629
C2784	'const remove_all_extents<T>::type &mpark::detail::visitation::base::at(const mpark::lib::cpp14::array<T,N> &,::size_t,Is...)': could not deduce template argument for 'const mpark::lib::cpp14::array<T,N> &' from 'void'	...\mpark\variant.hpp	633
C2780	'const T &mpark::detail::visitation::base::at(const T &)': expects 1 arguments - 2 provided	...\mpark\variant.hpp	633

"C'tor/d'tor is not implicitly called" error with Unreal Engine (VS 2017)

Hi,

Unfortunately mpark::variant doesn't compile in Unreal Engine projects. It gives the following errors:

Severity	Code	Description	Project	File	Line	Suppression State
Error	C4583	'mpark::detail::recursive_union<mpark::detail::Trait::Available,0,eos::morphablemodel::PcaModel,eos::morphablemodel::Blendshapes>::head_': destructor is not implicitly called	MyTestProject	variant.hpp	1353	
Error	C4583	'mpark::detail::recursive_union<mpark::detail::Trait::Available,0,eos::morphablemodel::PcaModel,eos::morphablemodel::Blendshapes>::tail_': destructor is not implicitly called	MyTestProject	variant.hpp	1353	

The line in question is:

    MPARK_VARIANT_RECURSIVE_UNION(Trait::Available,
                                  ~recursive_union() {});

Outside of Unreal Engine projects, it of course works flawlessly. Unfortunately, Unreal Engine has its own build system (UBT), and it's very peculiar on how it uses Visual Studio. It's basically a VS 2017 project and uses the VS 2017 compiler, but in C++14 mode, with the compiler flags set by some Unreal Engine C# build scripts (yes, it's horrible...).

Now I would be interested in: Why does this occur (apparently) only when building mpark::variant in Unreal Engine, which uses the VS 2017 compiler, so it should presumably work? What makes it fail? Could it be some peculiar compiler flag? Or is it a potential bug in mpark::variant? And is there a chance you could fix it? :-)

Thank you very much!

Compilation failed in Visual Studio 2017

Visual Studio version 15.8.3

tested code:

#include "mpark_variant.h"
int main()
{
	mpark::variant<int, float> obj;
}

Error message (sorry, it's in Chinese):

1>------ 已启动生成: 项目: playground, 配置: Debug Win32 ------
1>main.cpp
1>c:\repos\playground\playground\mpark_variant.h(935): error C2131: 表达式的计算结果不是常数
1>c:\repos\playground\playground\mpark_variant.h(935): note: 因读取超过生命周期的变量而失败
1>c:\repos\playground\playground\mpark_variant.h(935): note: 请参见“<traits_0>”的用法
1>c:\repos\playground\playground\mpark_variant.h(1757): note: 参见对正在编译的 类 模板 实例化 "mpark::detail::traits<int,float>" 的引用
1>c:\repos\playground\playground\mpark_variant.h(2059): note: 参见对正在编译的 类 模板 实例化 "mpark::detail::impl<int,float>" 的引用
1>c:\repos\playground\playground\main.cpp(4): note: 参见对正在编译的 类 模板 实例化 "mpark::variant<int,float>" 的引用
1>c:\repos\playground\playground\mpark_variant.h(963): error C2131: 表达式的计算结果不是常数
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.15.26726\include\initializer_list(42): note: 非常量参数或对非常量符号的引用导致了故障
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.15.26726\include\initializer_list(42): note: 请参见“$S3”的用法
1>c:\repos\playground\playground\mpark_variant.h(968): error C2131: 表达式的计算结果不是常数
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.15.26726\include\initializer_list(42): note: 非常量参数或对非常量符号的引用导致了故障
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.15.26726\include\initializer_list(42): note: 请参见“$S5”的用法
1>c:\repos\playground\playground\mpark_variant.h(973): error C2131: 表达式的计算结果不是常数
1>c:\repos\playground\playground\mpark_variant.h(973): note: 读取未初始化符号导致失败
1>c:\repos\playground\playground\mpark_variant.h(973): note: 请参见“copy_constructible_trait”的用法
1>c:\repos\playground\playground\mpark_variant.h(979): error C2131: 表达式的计算结果不是常数
1>c:\repos\playground\playground\mpark_variant.h(979): note: 读取未初始化符号导致失败
1>c:\repos\playground\playground\mpark_variant.h(979): note: 请参见“move_constructible_trait”的用法
1>c:\repos\playground\playground\mpark_variant.h(985): error C2131: 表达式的计算结果不是常数
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.15.26726\include\initializer_list(42): note: 非常量参数或对非常量符号的引用导致了故障
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.15.26726\include\initializer_list(42): note: 请参见“$S7”的用法
1>c:\repos\playground\playground\mpark_variant.h(1757): error C2975: “unnamed-parameter”:“mpark::detail::copy_assignment”的模板参数无效,应为编译时常量表达式
1>c:\repos\playground\playground\mpark_variant.h(1719): note: 参见“unnamed-parameter”的声明
1>c:\repos\playground\playground\mpark_variant.h(1757): error C2440: “specialization”: 无法从“int”转换为“mpark::detail::Trait”
1>c:\repos\playground\playground\mpark_variant.h(1757): note: 强制转换为枚举类型要求显式强制转换(static_cast、C 样式强制转换或函数样式强制转换)
1>c:\repos\playground\playground\mpark_variant.h(1741): error C2975: “unnamed-parameter”:“mpark::detail::move_assignment”的模板参数无效,应为编译时常量表达式
1>c:\repos\playground\playground\mpark_variant.h(1679): note: 参见“unnamed-parameter”的声明
1>c:\repos\playground\playground\mpark_variant.h(1757): note: 参见对正在编译的 类 模板 实例化 "mpark::detail::copy_assignment<mpark::detail::traits<int,float>,0>" 的引用
1>c:\repos\playground\playground\mpark_variant.h(1741): error C2440: “specialization”: 无法从“int”转换为“mpark::detail::Trait”
1>c:\repos\playground\playground\mpark_variant.h(1741): note: 强制转换为枚举类型要求显式强制转换(static_cast、C 样式强制转换或函数样式强制转换)
1>c:\repos\playground\playground\mpark_variant.h(1594): error C2975: “unnamed-parameter”:“mpark::detail::copy_constructor”的模板参数无效,应为编译时常量表达式
1>c:\repos\playground\playground\mpark_variant.h(1556): note: 参见“unnamed-parameter”的声明
1>c:\repos\playground\playground\mpark_variant.h(1701): note: 参见对正在编译的 类 模板 实例化 "mpark::detail::assignment<mpark::detail::traits<int,float>>" 的引用
1>c:\repos\playground\playground\mpark_variant.h(1741): note: 参见对正在编译的 类 模板 实例化 "mpark::detail::move_assignment<mpark::detail::traits<int,float>,0>" 的引用
1>c:\repos\playground\playground\mpark_variant.h(1594): error C2440: “specialization”: 无法从“int”转换为“mpark::detail::Trait”
1>c:\repos\playground\playground\mpark_variant.h(1594): note: 强制转换为枚举类型要求显式强制转换(static_cast、C 样式强制转换或函数样式强制转换)
1>c:\repos\playground\playground\mpark_variant.h(1578): error C2975: “unnamed-parameter”:“mpark::detail::move_constructor”的模板参数无效,应为编译时常量表达式
1>c:\repos\playground\playground\mpark_variant.h(1518): note: 参见“unnamed-parameter”的声明
1>c:\repos\playground\playground\mpark_variant.h(1594): note: 参见对正在编译的 类 模板 实例化 "mpark::detail::copy_constructor<Traits,0>" 的引用
1>        with
1>        [
1>            Traits=mpark::detail::traits<int,float>
1>        ]
1>c:\repos\playground\playground\mpark_variant.h(1578): error C2440: “specialization”: 无法从“int”转换为“mpark::detail::Trait”
1>c:\repos\playground\playground\mpark_variant.h(1578): note: 强制转换为枚举类型要求显式强制转换(static_cast、C 样式强制转换或函数样式强制转换)
1>c:\repos\playground\playground\mpark_variant.h(1471): error C2975: “unnamed-parameter”:“mpark::detail::destructor”的模板参数无效,应为编译时常量表达式
1>c:\repos\playground\playground\mpark_variant.h(1423): note: 参见“unnamed-parameter”的声明
1>c:\repos\playground\playground\mpark_variant.h(1540): note: 参见对正在编译的 类 模板 实例化 "mpark::detail::constructor<mpark::detail::traits<int,float>>" 的引用
1>c:\repos\playground\playground\mpark_variant.h(1578): note: 参见对正在编译的 类 模板 实例化 "mpark::detail::move_constructor<mpark::detail::traits<int,float>,0>" 的引用
1>c:\repos\playground\playground\mpark_variant.h(1471): error C2440: “specialization”: 无法从“int”转换为“mpark::detail::Trait”
1>c:\repos\playground\playground\mpark_variant.h(1471): note: 强制转换为枚举类型要求显式强制转换(static_cast、C 样式强制转换或函数样式强制转换)
1>c:\repos\playground\playground\mpark_variant.h(1472): error C2975: “unnamed-parameter”:“mpark::detail::destructor”的模板参数无效,应为编译时常量表达式
1>c:\repos\playground\playground\mpark_variant.h(1423): note: 参见“unnamed-parameter”的声明
1>c:\repos\playground\playground\mpark_variant.h(1472): error C2440: “specialization”: 无法从“int”转换为“mpark::detail::Trait”
1>c:\repos\playground\playground\mpark_variant.h(1472): note: 强制转换为枚举类型要求显式强制转换(static_cast、C 样式强制转换或函数样式强制转换)
1>c:\repos\playground\playground\mpark_variant.h(1595): error C2975: “unnamed-parameter”:“mpark::detail::copy_constructor”的模板参数无效,应为编译时常量表达式
1>c:\repos\playground\playground\mpark_variant.h(1556): note: 参见“unnamed-parameter”的声明
1>c:\repos\playground\playground\mpark_variant.h(1595): error C2440: “specialization”: 无法从“int”转换为“mpark::detail::Trait”
1>c:\repos\playground\playground\mpark_variant.h(1595): note: 强制转换为枚举类型要求显式强制转换(static_cast、C 样式强制转换或函数样式强制转换)
1>c:\repos\playground\playground\mpark_variant.h(1758): error C2975: “unnamed-parameter”:“mpark::detail::copy_assignment”的模板参数无效,应为编译时常量表达式
1>c:\repos\playground\playground\mpark_variant.h(1719): note: 参见“unnamed-parameter”的声明
1>c:\repos\playground\playground\mpark_variant.h(1758): error C2440: “specialization”: 无法从“int”转换为“mpark::detail::Trait”
1>c:\repos\playground\playground\mpark_variant.h(1758): note: 强制转换为枚举类型要求显式强制转换(static_cast、C 样式强制转换或函数样式强制转换)
1>已完成生成项目“playground.vcxproj”的操作 - 失败。
========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========

Optimization: If all alternatives are trivially copyable variant should never become valueless by exception

This would be equivalent to the optimization in libstdc++ https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=267614 .

There are doubts that this specific optimization is conformant. Because even the trivial move has observable side-effect (the address). Instead it might be better to move the value into a temporary, create the new one in-place. If any exception occurred: move the the temporary back.

The extra moves can be avoided if not only all alternatives are trivially copyable but also the specific constructor is noexcept.

A possible extension (but non conformant) would be to make a variant never valueless not only for trivially copyable but also for nothrow move/copy assignable (behind an option). This would be similar to #25. In practice extremely few types used as an alternative would have an observe a side-effect (the type would either have to have an ill-formed copy/move assignment (is a probably for testing with traits), or is nothrow move/copy assignable but the constructor used isn't nothrow and the move/copy has an observable side-effect.

It seems it would also make sense to make variant guranteed non-valueless if MPARK_EXCEPTIONS is false (as an extension to #30).

noexcept compiler warning with gcc

I'm getting a noexcept warning when using this with gcc. I've tried gcc 5.4.1, 6.3.0, and 7.2.0 all on Ubuntu 16.04 and get this warning on all of them. I'm using the 1.3.0 single header and compiling with the -std=c++11 flag.

This is the shortest example that I get the warning with:

#include "variant.hpp"

int main()
{
    mpark::visit([](bool&&) noexcept {}, mpark::variant<bool>());
    return 0;
}

It seems to be caused by using a visitor that doesn't throw an exception. Simply adding throw; to the lambda body and removing noexcept makes the warning go away, i.e. the following doesn't generate a warning:

mpark::visit([](bool&&) { throw 42; }, mpark::variant<bool>());

I've done a little bit of digging and can get rid of the warning by messing with

#define RETURN(...)                                          \
  noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { \
    return __VA_ARGS__;                                      \
  }

If I change noexcept(noexcept(__VA_ARGS__)) to virtually anything else, noexcept(true), noexcept(false), noexcept, or just remove it entirely, I no longer get the warning. I've gotten to the point where I'm not sure if this is a bug in the library, a compiler bug, or just me not understanding noexcept.

Here is the compiler output:

In file included from main.cpp:1:0:
variant.hpp: In instantiation of ‘constexpr decltype (forward<F>(f)((forward<As>)(mpark::lib::cpp17::invoke::as)...)) mpark::lib::cpp17::invoke(F&&, As&& ...) [with F = mpark::detail::visitation::variant::value_visitor<main()::<lambda(bool&&)> >; As = {mpark::detail::alt<0u, bool>}; decltype (forward<F>(f)((forward<As>)(mpark::lib::cpp17::invoke::as)...)) = void]’:
variant.hpp:1077:15:   required from ‘struct mpark::detail::visitation::base::dispatcher<0u>::impl<mpark::detail::visitation::variant::value_visitor<main()::<lambda(bool&&)> >&&, mpark::detail::base<(mpark::detail::Trait)0, bool>&&>’
variant.hpp:1085:11:   required by substitution of ‘template<class F, class ... Vs, unsigned int ...Is> static constexpr mpark::lib::cpp14::decay_t<decltype (& typename mpark::detail::visitation::base::dispatcher<Is ...>::impl<F, Vs ...>::dispatch)> mpark::detail::visitation::base::make_dispatch(mpark::lib::cpp14::index_sequence<Is ...>) [with F = mpark::detail::visitation::variant::value_visitor<main()::<lambda(bool&&)> >&&; Vs = {mpark::detail::base<(mpark::detail::Trait)0, bool>&&}; unsigned int ...Is = {0u}]’
variant.hpp:1140:15:   required from ‘struct mpark::detail::visitation::base::make_fmatrix_impl<mpark::detail::visitation::variant::value_visitor<main()::<lambda(bool&&)> >&&, mpark::detail::base<(mpark::detail::Trait)0, bool>&&>::impl<mpark::lib::cpp14::integer_sequence<unsigned int, 0u> >’
variant.hpp:1146:15:   required from ‘struct mpark::detail::visitation::base::make_fmatrix_impl<mpark::detail::visitation::variant::value_visitor<main()::<lambda(bool&&)> >&&, mpark::detail::base<(mpark::detail::Trait)0, bool>&&>::impl<mpark::lib::cpp14::integer_sequence<unsigned int>, mpark::lib::cpp14::integer_sequence<unsigned int, 0u> >’
variant.hpp:1153:11:   [ skipping 2 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
variant.hpp:1188:44:   required from ‘struct mpark::detail::visitation::fmatrix<mpark::detail::visitation::variant::value_visitor<main()::<lambda(bool&&)> >&&, mpark::detail::base<(mpark::detail::Trait)0, bool>&&>’
variant.hpp:1212:11:   required by substitution of ‘template<class Visitor, class ... Vs> static constexpr decltype (mpark::detail::visitation::base::at(mpark::detail::visitation::fmatrix<Visitor&&, decltype (as_base(forward<Vs>(vs)))...>::value, mpark::detail::visitation::alt::visit_alt::vs.index()...)(forward<Visitor>(visitor), as_base((forward<Vs>)(mpark::detail::visitation::alt::visit_alt::vs))...)) mpark::detail::visitation::alt::visit_alt(Visitor&&, Vs&& ...) [with Visitor = mpark::detail::visitation::variant::value_visitor<main()::<lambda(bool&&)> >; Vs = {mpark::detail::impl<bool>}]’
variant.hpp:1271:11:   required by substitution of ‘template<class Visitor, class ... Vs> static constexpr decltype (mpark::detail::visitation::alt::visit_alt(forward<Visitor>(visitor), (forward<Vs>)(mpark::detail::visitation::variant::visit_alt::vs).impl_ ...)) mpark::detail::visitation::variant::visit_alt(Visitor&&, Vs&& ...) [with Visitor = mpark::detail::visitation::variant::value_visitor<main()::<lambda(bool&&)> >; Vs = {mpark::variant<bool>}]’
variant.hpp:1286:11:   required by substitution of ‘template<class Visitor, class ... Vs> static constexpr decltype (mpark::detail::visitation::variant::visit_alt(mpark::detail::visitation::variant::make_value_visitor(forward<Visitor>(visitor)), (forward<Vs>)(mpark::detail::visitation::variant::visit_value::vs)...)) mpark::detail::visitation::variant::visit_value(Visitor&&, Vs&& ...) [with Visitor = main()::<lambda(bool&&)>; Vs = {mpark::variant<bool>}]’
variant.hpp:2342:5:   required by substitution of ‘template<class Visitor, class ... Vs> constexpr decltype (((mpark::detail::all(mpark::lib::cpp14::array<bool, sizeof... (Vs)>{{!mpark::visit::vs.valueless_by_exception()...}}) ? (void)(0) : mpark::throw_bad_variant_access()), mpark::detail::visitation::variant::visit_value(forward<Visitor>(visitor), (forward<Vs>)(mpark::visit::vs)...))) mpark::visit(Visitor&&, Vs&& ...) [with Visitor = main()::<lambda(bool&&)>; Vs = {mpark::variant<bool>}]’
main.cpp:5:64:   required from here
variant.hpp:545:29: error: noexcept-expression evaluates to ‘false’ because of a call to ‘constexpr decltype (mpark::detail::visitation::variant::visit_exhaustive_visitor_check<Visitor, decltype (forward<Alts>(alts).value)...>{}(forward<Visitor>(((const mpark::detail::visitation::variant::value_visitor<Visitor>*)this)->mpark::detail::visitation::variant::value_visitor<Visitor>::visitor_), (forward<Alts>)(mpark::detail::visitation::variant::value_visitor::operator()::alts).value ...)) mpark::detail::visitation::variant::value_visitor<Visitor>::operator()(Alts&& ...) const [with Alts = {mpark::detail::alt<0u, bool>}; Visitor = main()::<lambda(bool&&)>; decltype (mpark::detail::visitation::variant::visit_exhaustive_visitor_check<Visitor, decltype (forward<Alts>(alts).value)...>{}(forward<Visitor>(((const mpark::detail::visitation::variant::value_visitor<Visitor>*)this)->mpark::detail::visitation::variant::value_visitor<Visitor>::visitor_), (forward<Alts>)(mpark::detail::visitation::variant::value_visitor::operator()::alts).value ...)) = void]’ [-Werror=noexcept]
       inline constexpr auto invoke(F &&f, As &&... as)
                             ^
variant.hpp:1245:42: error: but ‘constexpr decltype (mpark::detail::visitation::variant::visit_exhaustive_visitor_check<Visitor, decltype (forward<Alts>(alts).value)...>{}(forward<Visitor>(((const mpark::detail::visitation::variant::value_visitor<Visitor>*)this)->mpark::detail::visitation::variant::value_visitor<Visitor>::visitor_), (forward<Alts>)(mpark::detail::visitation::variant::value_visitor::operator()::alts).value ...)) mpark::detail::visitation::variant::value_visitor<Visitor>::operator()(Alts&& ...) const [with Alts = {mpark::detail::alt<0u, bool>}; Visitor = main()::<lambda(bool&&)>; decltype (mpark::detail::visitation::variant::visit_exhaustive_visitor_check<Visitor, decltype (forward<Alts>(alts).value)...>{}(forward<Visitor>(((const mpark::detail::visitation::variant::value_visitor<Visitor>*)this)->mpark::detail::visitation::variant::value_visitor<Visitor>::visitor_), (forward<Alts>)(mpark::detail::visitation::variant::value_visitor::operator()::alts).value ...)) = void]’ does not throw; perhaps it should be declared ‘noexcept’ [-Werror=noexcept]
           inline constexpr DECLTYPE_AUTO operator()(Alts &&... alts) const

Figure out a plan for namespaces and versioning

If I were to define something like:

namespace mpark {

  namespace cpp17 {

    template <typename... Ts>
    class variant;

    template <typename F, typename... Vs>
    decltype(auto) visit(F&& f, Vs&&... vs);

  }  // namespace cpp17

  inline namespace v1 {

    template <typename... Ts>
    class variant;

    namespace unsafe {
      template <typename F, typename... Ts>
      decltype(auto) visit(F&& f, Vs&... vs);
    }  // namespace unsafe

    template <typename F, typename... Ts>
    decltype(auto) visit(F&& f, Vs&... vs);

  }  // namespace v1
  
}  // namespace mpark

I could provide a relaxed variant which provide useful non-standard extensions for mpark::variant, and still provide the standard version in mpark::cpp17::variant.

One can then define something like this to ensure that they don't use non-standard extensions,
and make a smooth transition from mpark/variant to std::variant.

namespace cpp17 = mpark::cpp17;
// Use `cpp17::variant`

Visit + Lambda

Hi,

I'm trying to use lambda instead of functor to visit a variant element. But is it possible to get compilation error when lambda do not handle all variant type ? Same behavior as a functor ?

Ex :

typedef mpark::variant<
    int8_t, uint8_t,
    double,
    std::string
> VariantValue;

VariantValue v{ (double)2.0 };

mpark::visit([](auto&& arg)
{
    using T = std::decay_t<decltype(arg)>;
    if (std::is_same_v<T, int8_t>)
        std::cout << "int8_t with value " << arg << '\n';
    else if (std::is_same_v<T, std::string>)
        std::cout << "std::string with value " << arg << '\n';
    else
        // static_assert(always_false<T>::value, "non-exhaustive visitor!");
        // static_assert(mpark::lib::is_invocable<T, arg>::value, "non-exhaustive visitor!");

        // ----------------------------------------------------------------------
        // I tried many thing but I'm always getting compilation error or
        // I can't achieve the behavior I'm look for.
}, v);

Important : I'm using Visual Studio 2015 Update 3 and GCC 4.9.1

Ref: http://en.cppreference.com/w/cpp/utility/variant/visit

compilation fails with msvc 19.12 (Visual Studio 2017, 15.5)

The variant class worked flawlessly together with MSVC so far but, unfortunately, with the latest update of Visual Studio 2017 to version 15.5.x it fails to compile. I'm not sure whether this is a compiler bug or something that requires updating the variant code.

When trying to compile variant/test/get.cpp, I get the following errors:

..\include\mpark/variant.hpp(575): error C3528: 'Is': the number of elements in this pack expansion does not match the number of elements in 'Js'
..\include\mpark/variant.hpp(582): note: see reference to function template instantiation 'auto mpark::detail::visitation::base::make_fmatrix_impl<F,mpark::detail::base<mpark::detail::Trait::Available,int,std::string>&,,0,1,>(mpark::lib::cpp14::integer_sequence<::size_t>,mpark::lib::cpp14::integer_sequence<::size_t,0,1>)' being compiled
        with
        [
            F=mpark::detail::dtor &&
        ]
..\include\mpark/variant.hpp(878): note: see reference to class template instantiation 'mpark::detail::base<mpark::detail::Trait::Available,int,std::string>' being compiled
..\include\mpark/variant.hpp(888): note: see reference to class template instantiation 'mpark::detail::destructor<Traits,mpark::detail::Trait::Available>' being compiled
        with
        [
            Traits=mpark::detail::traits<int,std::string>
        ]
..\include\mpark/variant.hpp(965): note: see reference to class template instantiation 'mpark::detail::constructor<mpark::detail::traits<int,std::string>>' being compiled
..\include\mpark/variant.hpp(1002): note: see reference to class template instantiation 'mpark::detail::move_constructor<mpark::detail::traits<int,std::string>,mpark::detail::Trait::Available>' being compiled
..\include\mpark/variant.hpp(1011): note: see reference to class template instantiation 'mpark::detail::copy_constructor<Traits,mpark::detail::Trait::Available>' being compiled
        with
        [
            Traits=mpark::detail::traits<int,std::string>
        ]
..\include\mpark/variant.hpp(1125): note: see reference to class template instantiation 'mpark::detail::assignment<mpark::detail::traits<int,std::string>>' being compiled
..\include\mpark/variant.hpp(1162): note: see reference to class template instantiation 'mpark::detail::move_assignment<mpark::detail::traits<int,std::string>,mpark::detail::Trait::Available>' being compiled
..\include\mpark/variant.hpp(1171): note: see reference to class template instantiation 'mpark::detail::copy_assignment<mpark::detail::traits<int,std::string>,mpark::detail::Trait::Available>' being compiled
..\include\mpark/variant.hpp(1470): note: see reference to class template instantiation 'mpark::detail::impl<int,std::string>' being compiled
get.cpp(17): note: see reference to class template instantiation 'mpark::variant<int,std::string>' being compiled
..\include\mpark/variant.hpp(633): note: see reference to function template instantiation 'auto mpark::detail::visitation::base::make_fmatrix<Visitor&&,mpark::detail::base<mpark::detail::Trait::Available,int,std::string>&>(void)' being compiled
        with
        [
            Visitor=mpark::detail::dtor
        ]
..\include\mpark/variant.hpp(878): note: see reference to function template instantiation 'decltype(auto) mpark::detail::visitation::base::visit_alt<mpark::detail::dtor,mpark::detail::destructor<Traits,mpark::detail::Trait::Available>&>(Visitor &&,mpark::detail::destructor<Traits,mpark::detail::Trait::Available> &)' being compiled
        with
        [
            Traits=mpark::detail::traits<int,std::string>,
            Visitor=mpark::detail::dtor
        ]
..\include\mpark/variant.hpp(878): note: while compiling class template member function 'void mpark::detail::destructor<Traits,mpark::detail::Trait::Available>::destroy(void) noexcept'
        with
        [
            Traits=mpark::detail::traits<int,std::string>
        ]
..\include\mpark/variant.hpp(870): note: see reference to function template instantiation 'void mpark::detail::destructor<Traits,mpark::detail::Trait::Available>::destroy(void) noexcept' being compiled
        with
        [
            Traits=mpark::detail::traits<int,std::string>
        ]
..\include\mpark/variant.hpp(574): error C2672: 'mpark::detail::visitation::base::make_farray': no matching overloaded function found
..\include\mpark/variant.hpp(575): error C2893: Failed to specialize function template 'mpark::lib::cpp14::array<std::common_type<std::decay<Fs>::type...>::type,sizeof...(Fs)> mpark::detail::visitation::base::make_farray(Fs &&...)'
..\include\mpark/variant.hpp(575): note: With the following template arguments:
..\include\mpark/variant.hpp(575): note: 'Fs={}'
..\include\mpark/variant.hpp(629): error C2672: 'mpark::detail::visitation::base::at': no matching overloaded function found
..\include\mpark/variant.hpp(633): error C2784: 'const remove_all_extents<T>::type &mpark::detail::visitation::base::at(const mpark::lib::cpp14::array<T,N> &,::size_t,Is...)': could not deduce template argument for 'const mpark::lib::cpp14::array<T,N> &' from 'void'
..\include\mpark/variant.hpp(500): note: see declaration of 'mpark::detail::visitation::base::at'
..\include\mpark/variant.hpp(633): error C2780: 'const T &mpark::detail::visitation::base::at(const T &)': expects 1 arguments - 2 provided
..\include\mpark/variant.hpp(495): note: see declaration of 'mpark::detail::visitation::base::at'

Warning: implicit conversion loses integer precision

When compiling with -Wshorten-64-to-32 on platforms where std::size_t is unsigned long, many warnings of the following form are produced:

include/mpark/variant.hpp:754:24: warning: implicit conversion loses integer precision: 'std::size_t' (aka 'unsigned long') to 'unsigned int' [-Wshorten-64-to-32]
          lhs.index_ = rhs.index();
                     ~ ^~~~~~~~~~~

vector of move-only type doesn't work as element

Apparently a vector of a move-only type doesn't seem to work as an element type of this variant implementation. I don't quite understand why, as unique_ptr by itself does work, and as I understand it a vector of this type should be moveable (and not copyable) just like unique_ptr itself.

E.g., using gcc 7.3.0 with "--std=c++17" (also with gcc 6.3.0), the following code does not compile:

#include <vector>
#include <memory>
#include "variant.hpp"

int main ()
{
  mpark::variant <std::vector <std::unique_ptr <int>>> foo;
}

In file included from /usr/local/gcc-7/include/c++/7.3.0/vector:62:0,
                 from variant-master/include/mpark/test.cpp:1:
/usr/local/gcc-7/include/c++/7.3.0/bits/stl_construct.h: In instantiation of 'void std::_Construct(_T1*, _Args&& ...) [with _T1 = std::unique_ptr<int>; _Args = {const std::unique_ptr<int, std::default_delete<int> >&}]':
/usr/local/gcc-7/include/c++/7.3.0/bits/stl_uninitialized.h:83:18:   required from 'static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const std::unique_ptr<int>*, std::vector<std::unique_ptr<int> > >; _ForwardIterator = std::unique_ptr<int>*; bool _TrivialValueTypes = false]'
/usr/local/gcc-7/include/c++/7.3.0/bits/stl_uninitialized.h:134:15:   required from '_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const std::unique_ptr<int>*, std::vector<std::unique_ptr<int> > >; _ForwardIterator = std::unique_ptr<int>*]'
/usr/local/gcc-7/include/c++/7.3.0/bits/stl_uninitialized.h:289:37:   required from '_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = __gnu_cxx::__normal_iterator<const std::unique_ptr<int>*, std::vector<std::unique_ptr<int> > >; _ForwardIterator = std::unique_ptr<int>*; _Tp = std::unique_ptr<int>]'
/usr/local/gcc-7/include/c++/7.3.0/bits/stl_vector.h:331:31:   required from 'std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with _Tp = std::unique_ptr<int>; _Alloc = std::allocator<std::unique_ptr<int> >]'
/usr/local/gcc-7/include/c++/7.3.0/type_traits:1406:12:   required from 'struct std::is_trivially_copy_constructible<std::vector<std::unique_ptr<int> > >'
variant-master/include/mpark/variant.hpp:377:18:   required from 'constexpr mpark::detail::Trait mpark::detail::trait() [with T = std::vector<std::unique_ptr<int> >; IsTriviallyAvailable = std::is_trivially_copy_constructible; IsAvailable = std::is_copy_constructible]'
variant-master/include/mpark/variant.hpp:416:57:   required from 'constexpr const mpark::detail::Trait mpark::detail::traits<std::vector<std::unique_ptr<int, std::default_delete<int> >, std::allocator<std::unique_ptr<int, std::default_delete<int> > > > >::copy_constructible_trait'
variant-master/include/mpark/variant.hpp:424:23:   required from 'constexpr const mpark::detail::Trait mpark::detail::traits<std::vector<std::unique_ptr<int, std::default_delete<int> >, std::allocator<std::unique_ptr<int, std::default_delete<int> > > > >::copy_assignable_trait'
variant-master/include/mpark/variant.hpp:1205:11:   required from 'class mpark::detail::impl<std::vector<std::unique_ptr<int, std::default_delete<int> >, std::allocator<std::unique_ptr<int, std::default_delete<int> > > > >'
variant-master/include/mpark/variant.hpp:1504:25:   required from 'class mpark::variant<std::vector<std::unique_ptr<int, std::default_delete<int> >, std::allocator<std::unique_ptr<int, std::default_delete<int> > > > >'
variant-master/include/mpark/test.cpp:7:56:   required from here
/usr/local/gcc-7/include/c++/7.3.0/bits/stl_construct.h:75:7: error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]'
     { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/local/gcc-7/include/c++/7.3.0/memory:80:0,
                 from variant-master/include/mpark/test.cpp:2:
/usr/local/gcc-7/include/c++/7.3.0/bits/unique_ptr.h:388:7: note: declared here
       unique_ptr(const unique_ptr&) = delete;
       ^~~~~~~~~~

Whereas the same code with std::variant does compile (gcc 7.3.0 only; 6.3.0 doesn't yet have std::variant):

#include <vector>
#include <memory>
#include <variant>

int main ()
{
  std::variant <std::vector <std::unique_ptr <int>>> foo;
}

Any ideas? (Or workarounds?)

Try to support older versions of GCC

Currently, the lack of type traits such as is_trivially_constructible prevent compilation on GCC 4.9. Consider replacing the middle layers with a simpler is_trivially_copyable definition from #8.

Issues packaging with conan.io

Hi!

I'm trying to package this library (v1.3.0) using conan.io, you can see my ongoing work in this repo and I want to share with you some issues I'm facing, just in case you have an opinion about them.

As the idea is to work with packaged dependencies, I am not using the 3rdparty directory with the submodules but the gtest package provided by bincrafters (release-v1.8.0). Two comments when using this packaged library:

  • File internal_utils.cmake is not packaged, so the function that is used here won't work. I've created another gtest package that export this file and included it, but I'm wondering if this file is intended to be used by packages depending on googletests or if it is just an internal one.
  • When you link against gtest_main here I have to link also against gtest, I've to check which one is the correct one.

If you are interested on having this library packaged with conan, I can work further on this and create a PR, otherwise I will keep using these workarounds.

PD.- btw, I came to your library following the dependencies being used by spdlog_setup.

Fails with Intel compiler in C++11 mode

The following simplest example:

#include "variant.hpp"

int main()
{
    using MyVariant = mpark::variant<int, float>;
    MyVariant x = 5;
}

fails to compile with the Intel compiler if I pass it -std=c++11, but compiles fine, if I give it -std=c++14. It compiles in C++11 mode with GCC and Clang.

The compiler version is:

icpc (ICC) 18.0.1 20171018
Copyright (C) 1985-2017 Intel Corporation.  All rights reserved.

The error it reports:

In file included from example.cpp(1):
variant.hpp(995): warning #3801: deduced return types are a C++14 feature
          inline static constexpr auto &&get_alt(V &&v, in_place_index_t<0>) {
                                  ^

In file included from example.cpp(1):
variant.hpp(1000): warning #3801: deduced return types are a C++14 feature
          inline static constexpr auto &&get_alt(V &&v, in_place_index_t<I>) {
                                  ^

In file included from example.cpp(1):
variant.hpp(1026): warning #3801: deduced return types are a C++14 feature
          inline static constexpr AUTO_REFREF get_alt(V &&v)
                                  ^

In file included from example.cpp(1):
variant.hpp(1033): warning #3801: deduced return types are a C++14 feature
          inline static constexpr AUTO_REFREF get_alt(V &&v)
                                  ^

In file included from example.cpp(1):
variant.hpp(1076): error: expected an identifier
              inline static constexpr DECLTYPE_AUTO dispatch(F f, Vs... vs)
                                      ^

In file included from example.cpp(1):
variant.hpp(1076): error: "auto" is not allowed here
              inline static constexpr DECLTYPE_AUTO dispatch(F f, Vs... vs)
                                      ^

In file included from example.cpp(1):
variant.hpp(1076): error #303: explicit type is missing ("int" assumed)
              inline static constexpr DECLTYPE_AUTO dispatch(F f, Vs... vs)
                                      ^

In file included from example.cpp(1):
variant.hpp(1076): error: expected a ";"
              inline static constexpr DECLTYPE_AUTO dispatch(F f, Vs... vs)
                                                    ^

In file included from example.cpp(1):
variant.hpp(1080): warning #12: parsing restarts here after previous syntax error
            };
            ^

In file included from example.cpp(1):
variant.hpp(1084): warning #3801: deduced return types are a C++14 feature
          inline static constexpr AUTO make_dispatch(lib::index_sequence<Is...>)
                                  ^

In file included from example.cpp(1):
variant.hpp(1088): warning #3801: deduced return types are a C++14 feature
          inline static constexpr AUTO make_fdiagonal_impl()


[...]


In file included from example.cpp(1):
variant.hpp(2341): error: expected a ";"
    inline constexpr DECLTYPE_AUTO visit(Visitor &&visitor, Vs &&... vs)
                                   ^

In file included from example.cpp(1):
variant.hpp(2381): warning #12: parsing restarts here after previous syntax error
      }  // namespace hash
      ^

In file included from example.cpp(1):
variant.hpp(2383): error: expected a declaration
    }  // namespace detail
    ^

In file included from example.cpp(1):
variant.hpp(2423): warning #12: parsing restarts here after previous syntax error
                      v);
                        ^

In file included from example.cpp(1):
variant.hpp(2424): error: expected a declaration
        return hash_combine(result, hash<std::size_t>{}(v.index()));
        ^

In file included from example.cpp(1):
variant.hpp(2425): error: expected a declaration
      }
      ^

In file included from example.cpp(1):
variant.hpp(2437): warning #12: parsing restarts here after previous syntax error
      };
       ^

In file included from example.cpp(1):
variant.hpp(2443): error: expected a declaration
    };
    ^

In file included from example.cpp(1):
variant.hpp(2446): error: hash is not a template
    struct hash<mpark::monostate> {
           ^

In file included from example.cpp(1):
variant.hpp(2455): error: expected a declaration
  }  // namespace std
  ^

example.cpp(7): warning #12: parsing restarts here after previous syntax error

compilation aborted for example.cpp (code 2)

Add support for MSVC 2015 cl compiler

MSVC 2015 Update 3 cl.exe cant compile example from https://wandbox.org/permlink/b4NDy4VupqPWkjva
https://pastebin.com/iwe2sVKy

from slack cpplang:
k-ballo:

the workaround is rather trivial, just move the noexcept(...) call within a class body, but that's something that only the library can do
msvc uses different name lookup implementations depending on the context in which an expression appears.. it has at least 3 different ones, each with its own different bugs

Crash under MSVC (VS 2015 update 3)

When we have a global object that contains a variant instance that stores a std::unique_ptr the variant creation crashes the program. I tried to illustrate the minimal example and provide a stacktrace of the crash. Am I missing something? I don't think the code does anything illegal?

Crash occurs on MSVC (GCC does not crash);

Callstack:

0000000000000000() (Unknown Source:0)
tests.exe!mpark::detail::visitation::alt::visit_alt<mpark::detail::dtor,mpark::detail::destructor<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<int> > >,1> & __ptr64>(mpark::detail::dtor && visitor, mpark::detail::destructor<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<int> > >,1> & <vs_0>) Line 1212 (d:\dev\contrib\variant.hpp:1212)
tests.exe!mpark::detail::destructor<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<int> > >,1>::destroy() Line 1461 (d:\dev\contrib\variant.hpp:1461)
tests.exe!mpark::detail::assignment<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<int> > > >::emplace<1,std::unique_ptr<int,std::default_delete<int> > >(std::unique_ptr<int,std::default_delete<int> > && <args_0>) Line 1606 (d:\dev\contrib\variant.hpp:1606)
tests.exe!`mpark::detail::assignment<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<int> > > >::assign_alt<1,std::unique_ptr<int,std::default_delete<int> >,std::unique_ptr<int,std::default_delete<int> > >'::`7'::<unnamed-type-impl>::operator()(std::integral_constant<bool,1> __formal) Line 1639 (d:\dev\contrib\variant.hpp:1639)
tests.exe!mpark::detail::assignment<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<int> > > >::assign_alt<1,std::unique_ptr<int,std::default_delete<int> >,std::unique_ptr<int,std::default_delete<int> > >(mpark::detail::alt<1,std::unique_ptr<int,std::default_delete<int> > > & a, std::unique_ptr<int,std::default_delete<int> > && arg) Line 1650 (d:\dev\contrib\variant.hpp:1650)
tests.exe!mpark::detail::impl<int,std::unique_ptr<int,std::default_delete<int> > >::assign<1,std::unique_ptr<int,std::default_delete<int> > >(std::unique_ptr<int,std::default_delete<int> > && arg) Line 1765 (d:\dev\contrib\variant.hpp:1765)
tests.exe!mpark::variant<int,std::unique_ptr<int,std::default_delete<int> > >::operator=<std::unique_ptr<int,std::default_delete<int> >,0,1,std::unique_ptr<int,std::default_delete<int> >,0>(std::unique_ptr<int,std::default_delete<int> > && arg) Line 1982 (d:\dev\contrib\variant.hpp:1982)
tests.exe!Bar::Bar() Line 214 (d:\dev\tests\core\ConfigTests.cpp:214)
tests.exe!Foo::Foo() Line 221 (d:\dev\tests\core\ConfigTests.cpp:221)
tests.exe!`dynamic initializer for 'instance''() Line 223 (d:\dev\tests\core\ConfigTests.cpp:223)
ucrtbased.dll!00007fffdfb20479() (Unknown Source:0)
tests.exe!__scrt_common_main_seh() Line 223 (f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:223)
tests.exe!__scrt_common_main() Line 296 (f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:296)
tests.exe!mainCRTStartup() Line 17 (f:\dd\vctools\crt\vcstartup\src\startup\exe_main.cpp:17)
kernel32.dll!00007ff80f091fe4() (Unknown Source:0)
ntdll.dll!00007ff80f79efb1() (Unknown Source:0)

Repro:

using UniquePointer = std::unique_ptr<int>;
using VariantType = mpark::variant<int, UniquePointer>;

struct Bar
{
    Bar()
    {
        auto ptr = std::make_unique<int>();
        v = std::move( ptr ); // this crashes
    }
    VariantType v;
};

struct Foo {
    Foo()
    {
    }
    Bar store;
} instance; // global instance

missing type_switch

Hi Michael, I was looking for type_switch and I was unable to find it. Have you implemented it?

Intellisense stop working in VS 2017 after including mpark/varaint.hpp

We've narrowed the issue to the lib.hpp file in mpark variant

These lines are messing up intellisense(Lines 393-397 in lib.hpp of mpark)

template <std::size_t I, typename... Ts>
using type_pack_element = typename type_pack_element_impl<I, Ts...>::type;

template <std::size_t I, typename... Ts>
using type_pack_element_t = typename type_pack_element<I, Ts...>::type;

Could you check it and fix it? you know, It's painful to work without intellisense.

Codegen issue

Hey, I found some pretty not great codegen for std::visit. I mentioned this to Louis Dionne (a libc++ maintainer), and asked him if there was a reason switch case was not used for the common case (e.g. visit one variant for under ten types). You can see the differences in assembly (std, boost, switch-case) for 2 examples here: https://gcc.godbolt.org/z/Kt8ZNf.

He suggested opening an issue here, because he said that you were the expert on implementing variant :-). Someone also told me that there was an open bug report on gcc, so I wrote things up fairly neatly there in more detail: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78113. The gist of it is that the constexpr table of function pointer approach just doesn't get inlined even with brand new compilers, and you can see that even relatively easy optimization like simply optimizing out an empty visitor can't be done. Switch case can't really be doen generically, but it seems easy to generate a bit of code such that you can handle visit for a single variant for up to N types (have N equal e.g. 10). This code is actually fairly simple, and gives massive improvements in assembly for the very common case, at no runtime cost to the other cases, and just very minimal compile cost (most likely).

Let me know your thoughts!

Add workaround for libstdc++ < 5.0

libstdc++ < 5.0 doesn't provide std::is_trivially_copyable but the old proposed type traits. The following workaround can be added to support libstdc++ < 5.0

#if defined(__GLIBCXX__) && __GLIBCXX__ < 20150801
namespace std {
template <typename T>
struct is_trivially_copyable : integral_constant<bool, __has_trivial_copy(T)> {
};
}  // namespace std
#endif  // GLIBCXX macro

Rarer `valueless_by_exception`

Implement section III of P0308 as a non-standard version (outside of cpp17 namespace).

Types such as variant<int, double> should not ever get into a valueless_by_exception state.
Something like:

template <std::size_t I, typename... Args>
inline auto &emplace(Args &&... args) {
  using T = variants::lib::type_pack_element_t<I, Ts...>;
  if constexpr (std::is_nothrow_constructible_v<T, Args...> ||
                !std::is_nothrow_move_constructible_v<T>) {
    this->destroy();
    auto &result = this->construct_alt(access::base::get_alt<I>(*this),
                                       std::forward<Args>(args)...);
    this->index_ = I;
    return result;
  } else {
    T temp(std::forward<Args>(args)...);
    this->destroy();
    auto &result = this->construct_alt(access::base::get_alt<I>(*this), std::move(temp));
    this->index_ = I;
    return result;
  }
}

store size_t in a variant ?

Hi,

I am trying to store size_t as well as int64_t, double, bool, string in a variant. Storing the 4 last types work fine, but I get a bad_variant_access when trying to get/set the size_t with this code :

#include <iostream>
#include <cstdint>
#define MPARK_EXCEPTIONS
#include <mpark/variant.hpp>

using namespace std;  // i know it's bad, it's just for testing

int main()
{
    mpark::variant<int64_t, double, bool, string, size_t> v;
    mpakr::get<size_t>(v) = 15;  // right there
    return 0;
}

edit : updating code to fix compile errors

ICE with GCC 7.3.1

The following snippet triggers an ICE on GCC 7.3.1

using var_t = xtl::variant<int, long, double, std::string>;
std::vector<var_t> vec = { 10, 15l, 1.5, "hello" };
/home/wolfv/Programs/xtl/include/xtl/xvariant_impl.hpp: In substitution of ‘template<long unsigned int I, class ... Ts> using type_pack_element_t = typename mpark::lib::type_pack_element_impl::type::type [with long unsigned int I = I; Ts = {int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >}]’:
/home/wolfv/Programs/xtl/include/xtl/xvariant_impl.hpp:1900:9:   required by substitution of ‘template<class Arg, class Decayed, typename std::enable_if<(! std::is_same<Decayed, mpark::variant<int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::value), int>::type <anonymous>, typename std::enable_if<(! mpark::detail::is_in_place_index<Decayed>::value), int>::type <anonymous>, typename std::enable_if<(! mpark::detail::is_in_place_type<Decayed>::value), int>::type <anonymous>, long unsigned int I, class T, typename std::enable_if<std::is_constructible<T, Arg>::value, int>::type <anonymous> > constexpr mpark::variant<int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::variant(Arg&&) [with Arg = mpark::variant<int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&; Decayed = mpark::variant<int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >; typename std::enable_if<(! std::is_same<Decayed, mpark::variant<int, long int, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::value), int>::type <anonymous> = <missing>; typename std::enable_if<(! mpark::detail::is_in_place_index<Decayed>::value), int>::type <anonymous> = <missing>; typename std::enable_if<(! mpark::detail::is_in_place_type<Decayed>::value), int>::type <anonymous> = <missing>; long unsigned int I = <missing>; T = <missing>; typename std::enable_if<std::is_constructible<T, Arg>::value, int>::type <anonymous> = <missing>]’
/home/wolfv/Programs/xtl/test/main.cpp:57:24:   required from here
/home/wolfv/Programs/xtl/include/xtl/xvariant_impl.hpp:1900:9: internal compiler error: unexpected expression ‘I’ of kind template_parm_index
         typename T = lib::type_pack_element_t<I, Ts...>,
         ^~~~~~~~

We should probably also submit this bug as regression to the GCC folks?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.