mpark / variant Goto Github PK
View Code? Open in Web Editor NEWC++17 `std::variant` for C++11/14/17
Home Page: https://mpark.github.io/variant
License: Boost Software License 1.0
C++17 `std::variant` for C++11/14/17
Home Page: https://mpark.github.io/variant
License: Boost Software License 1.0
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)
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:
or even just provide a single header
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?
Specifically, a variant that contains references as alternatives are lacking constexpr
tests.
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.
A single-header file will be shipped with each release.
I'd rather not update it per-commit, so it won't be kept in the repo.
It will be generated by support/single-header.py
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;
.
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
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
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!
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 个 ==========
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).
Build failures for example, aren't being reported correctly as CI failures: https://ci.appveyor.com/project/mpark/variant/build/1.0.981/job/rpfh4dwprxo4stym
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
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`
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
This needs some perf tests to demonstrate their needs before introducing them.
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'
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();
~ ^~~~~~~~~~~
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?)
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.
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:
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.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.
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)
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
For example, This line currently causes a -pedantic
warning when compiling with GCC 6.3.0 due to the extra semicolon.
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
The lack of implementation of P0513 currently breaks the build.
Hi Michael, I was looking for type_switch
and I was unable to find it. Have you implemented it?
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.
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!
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
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;
}
}
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
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?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.