mpark / variant

C++17 `std::variant` for C++11/14/17
https://mpark.github.io/variant
Boost Software License 1.0
659 stars 88 forks source link

Use constexpr compiler bug workaround for VS2017 version 15.9 #57

Closed nightlark closed 5 years ago

nightlark commented 5 years ago

The latest version of Visual Studio 2017 (15.9) is still affected by the constexpr compiler bug, and they've incremented MSC_VER by 1.

mpark commented 5 years ago

Hi @nightlark, thanks for the patch!

Do you have a minimal repro of this by any chance along with the error message?

The previous fix regarding MPARK_CPP14_CONSTEXPR was kind of a hack that I didn't really didn't dig too deeply into because the macro didn't have significant impact. At this point however, I've implemented a more efficient visitation mechanism that relies on that macro #56.

I think I'd like to dig a bit deeper into the issue here. The latest master build succeeded with VS 2017 15.9, so it seems like there's at least a missing test case...

cc @mgieseki

mgieseki commented 5 years ago

I can confirm the compilation failure with the latest variant sources from master (using VS 2017, version 15.9.5). For example, the following code fails to compile with the messages appended below (sorry, I've only the German locale installed at the moment).

#include <mpark/variant.hpp>
#include <memory>
#include <vector>

struct S {
  S (int n) : var(n) {}
  mpark::variant<int, std::unique_ptr<int>> var;
};

int main () {
  std::vector<S> vec;
  vec.emplace_back(0);
}

Error output:

..\libs\variant\include\mpark/variant.hpp(931): error C2280: "std::unique_ptr<int,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)" : Es wurde versucht, auf eine gelöschte Funktion zu verweisen
        with
        [
            _Ty=int
        ]
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include\memory(2337): note: Siehe Deklaration von "std::unique_ptr<int,std::default_delete<_Ty>>::unique_ptr"
        with
        [
            _Ty=int
        ]
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include\memory(2337): note: "std::unique_ptr<int,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)": Die Funktion wurde explizit gelöscht.
        with
        [
            _Ty=int
        ]
..\libs\variant\include\mpark/variant.hpp(1120): note: Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-Vorlage "mpark::detail::alt<1,T>::alt<T>(mpark::in_place_t,T &&)".
        with
        [
            T=std::unique_ptr<int,std::default_delete<int>>
        ]
..\libs\variant\include\mpark/variant.hpp(1120): note: Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-Vorlage "mpark::detail::alt<1,T>::alt<T>(mpark::in_place_t,T &&)".
        with
        [
            T=std::unique_ptr<int,std::default_delete<int>>
        ]
..\libs\variant\include\mpark/variant.hpp(1133): note: Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-Vorlage "T &mpark::detail::constructor<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<_Ty>>>>::construct_alt<1,T,const T>(mpark::detail::alt<1,T> &,const T &&)".
        with
        [
            T=std::unique_ptr<int,std::default_delete<int>>,
            _Ty=int
        ]
..\libs\variant\include\mpark/variant.hpp(1132): note: Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-Vorlage "T &mpark::detail::constructor<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<_Ty>>>>::construct_alt<1,T,const T>(mpark::detail::alt<1,T> &,const T &&)".
        with
        [
            T=std::unique_ptr<int,std::default_delete<int>>,
            _Ty=int
        ]
c:\users\martin\develop\cpp\dvisvgm\libs\variant\include\mpark\lib.hpp(230): note: Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-Vorlage "void mpark::detail::constructor<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<_Ty>>>>::generic_construct::<lambda_a372bf6c60ba10b92805b4aebac9455e>::operator ()<mpark::detail::alt<1,T>,const mpark::detail::alt<1,T>>(mpark::detail::alt<1,T> &,const mpark::detail::alt<1,T> &&) const".
        with
        [
            _Ty=int,
            T=std::unique_ptr<int,std::default_delete<int>>
        ]
..\libs\variant\include\mpark/variant.hpp(618): note: Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-Vorlage "R mpark::detail::visitation::base::dispatcher<true,R>::dispatch_case<1,T,mpark::detail::base<mpark::detail::Trait::Available,int,std::unique_ptr<int,std::default_delete<_Ty>>>&,mpark::detail::base<mpark::detail::Trait::Available,int,std::unique_ptr<_Ty,std::default_delete<_Ty>>>>(F &&,mpark::detail::base<mpark::detail::Trait::Available,int,std::unique_ptr<_Ty,std::default_delete<_Ty>>> &,mpark::detail::base<mpark::detail::Trait::Available,int,std::unique_ptr<_Ty,std::default_delete<_Ty>>> &&)".
        with
        [
            R=void,
            T=mpark::detail::constructor<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<int>>>>::generic_construct::<lambda_a372bf6c60ba10b92805b4aebac9455e>,
            _Ty=int,
            F=mpark::detail::constructor<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<int>>>>::generic_construct::<lambda_a372bf6c60ba10b92805b4aebac9455e>
        ]
..\libs\variant\include\mpark/variant.hpp(618): note: Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-Vorlage "R mpark::detail::visitation::base::dispatcher<true,R>::dispatch_case<1,T,mpark::detail::base<mpark::detail::Trait::Available,int,std::unique_ptr<int,std::default_delete<_Ty>>>&,mpark::detail::base<mpark::detail::Trait::Available,int,std::unique_ptr<_Ty,std::default_delete<_Ty>>>>(F &&,mpark::detail::base<mpark::detail::Trait::Available,int,std::unique_ptr<_Ty,std::default_delete<_Ty>>> &,mpark::detail::base<mpark::detail::Trait::Available,int,std::unique_ptr<_Ty,std::default_delete<_Ty>>> &&)".
        with
        [
            R=void,
            T=mpark::detail::constructor<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<int>>>>::generic_construct::<lambda_a372bf6c60ba10b92805b4aebac9455e>,
            _Ty=int,
            F=mpark::detail::constructor<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<int>>>>::generic_construct::<lambda_a372bf6c60ba10b92805b4aebac9455e>
        ]
..\libs\variant\include\mpark/variant.hpp(837): note: Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-Vorlage "R mpark::detail::visitation::base::dispatcher<true,R>::dispatch_at<0,T,mpark::detail::base<mpark::detail::Trait::Available,int,std::unique_ptr<int,std::default_delete<_Ty>>>&,mpark::detail::base<mpark::detail::Trait::Available,int,std::unique_ptr<_Ty,std::default_delete<_Ty>>>>(size_t,F &&,V,mpark::detail::base<mpark::detail::Trait::Available,int,std::unique_ptr<_Ty,std::default_delete<_Ty>>> &&)".
        with
        [
            R=void,
            T=mpark::detail::constructor<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<int>>>>::generic_construct::<lambda_a372bf6c60ba10b92805b4aebac9455e>,
            _Ty=int,
            F=mpark::detail::constructor<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<int>>>>::generic_construct::<lambda_a372bf6c60ba10b92805b4aebac9455e>,
            V=mpark::detail::base<mpark::detail::Trait::Available,int,std::unique_ptr<int,std::default_delete<int>>> &
        ]
..\libs\variant\include\mpark/variant.hpp(829): note: Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-Vorlage "R mpark::detail::visitation::base::dispatcher<true,R>::dispatch_at<0,T,mpark::detail::base<mpark::detail::Trait::Available,int,std::unique_ptr<int,std::default_delete<_Ty>>>&,mpark::detail::base<mpark::detail::Trait::Available,int,std::unique_ptr<_Ty,std::default_delete<_Ty>>>>(size_t,F &&,V,mpark::detail::base<mpark::detail::Trait::Available,int,std::unique_ptr<_Ty,std::default_delete<_Ty>>> &&)".
        with
        [
            R=void,
            T=mpark::detail::constructor<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<int>>>>::generic_construct::<lambda_a372bf6c60ba10b92805b4aebac9455e>,
            _Ty=int,
            F=mpark::detail::constructor<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<int>>>>::generic_construct::<lambda_a372bf6c60ba10b92805b4aebac9455e>,
            V=mpark::detail::base<mpark::detail::Trait::Available,int,std::unique_ptr<int,std::default_delete<int>>> &
        ]
..\libs\variant\include\mpark/variant.hpp(1140): note: Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-Vorlage "R mpark::detail::visitation::alt::visit_alt_at<mpark::detail::constructor<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<_Ty>>>>::generic_construct::<lambda_a372bf6c60ba10b92805b4aebac9455e>,mpark::detail::constructor<mpark::detail::traits<int,std::unique_ptr<_Ty,std::default_delete<_Ty>>>>&,T>(size_t,Visitor &&,mpark::detail::constructor<mpark::detail::traits<int,std::unique_ptr<_Ty,std::default_delete<_Ty>>>> &,T &&)".
        with
        [
            R=void,
            _Ty=int,
            T=mpark::detail::move_constructor<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<int>>>,mpark::detail::Trait::Available>,
            Visitor=mpark::detail::constructor<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<int>>>>::generic_construct::<lambda_a372bf6c60ba10b92805b4aebac9455e>
        ]
..\libs\variant\include\mpark/variant.hpp(1176): note: Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-Vorlage "void mpark::detail::constructor<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<_Ty>>>>::generic_construct<mpark::detail::move_constructor<mpark::detail::traits<int,std::unique_ptr<_Ty,std::default_delete<_Ty>>>,mpark::detail::Trait::Available>>(mpark::detail::constructor<mpark::detail::traits<int,std::unique_ptr<_Ty,std::default_delete<_Ty>>>> &,Rhs &&)".
        with
        [
            _Ty=int,
            Rhs=mpark::detail::move_constructor<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<int>>>,mpark::detail::Trait::Available>
        ]
..\libs\variant\include\mpark/variant.hpp(1170): note: Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-Vorlage "void mpark::detail::constructor<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<_Ty>>>>::generic_construct<mpark::detail::move_constructor<mpark::detail::traits<int,std::unique_ptr<_Ty,std::default_delete<_Ty>>>,mpark::detail::Trait::Available>>(mpark::detail::constructor<mpark::detail::traits<int,std::unique_ptr<_Ty,std::default_delete<_Ty>>>> &,Rhs &&)".
        with
        [
            _Ty=int,
            Rhs=mpark::detail::move_constructor<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<int>>>,mpark::detail::Trait::Available>
        ]
..\libs\variant\include\mpark/variant.hpp(1176): note: Bei der Kompilierung von Klasse Vorlage der mpark::detail::move_constructor<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<_Ty>>>,mpark::detail::Trait::Available>::move_constructor(mpark::detail::move_constructor<mpark::detail::traits<int,std::unique_ptr<_Ty,std::default_delete<_Ty>>>,mpark::detail::Trait::Available> &&) noexcept-Memberfunktion
        with
        [
            _Ty=int
        ]
varianttest.cpp(15): note: Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-Vorlage "mpark::detail::move_constructor<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<_Ty>>>,mpark::detail::Trait::Available>::move_constructor(mpark::detail::move_constructor<mpark::detail::traits<int,std::unique_ptr<_Ty,std::default_delete<_Ty>>>,mpark::detail::Trait::Available> &&) noexcept".
        with
        [
            _Ty=int
        ]
..\libs\variant\include\mpark/variant.hpp(1217): note: Siehe Verweis auf die Klasse Vorlage-Instanziierung "mpark::detail::move_constructor<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<_Ty>>>,mpark::detail::Trait::Available>", die kompiliert wird.
        with
        [
            _Ty=int
        ]
..\libs\variant\include\mpark/variant.hpp(1222): note: Siehe Verweis auf die Klasse Vorlage-Instanziierung "mpark::detail::copy_constructor<Traits,mpark::detail::Trait::Unavailable>", die kompiliert wird.
        with
        [
            Traits=mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<int>>>
        ]
..\libs\variant\include\mpark/variant.hpp(1336): note: Siehe Verweis auf die Klasse Vorlage-Instanziierung "mpark::detail::assignment<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<_Ty>>>>", die kompiliert wird.
        with
        [
            _Ty=int
        ]
..\libs\variant\include\mpark/variant.hpp(1377): note: Siehe Verweis auf die Klasse Vorlage-Instanziierung "mpark::detail::move_assignment<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<_Ty>>>,mpark::detail::Trait::Available>", die kompiliert wird.
        with
        [
            _Ty=int
        ]
..\libs\variant\include\mpark/variant.hpp(1382): note: Siehe Verweis auf die Klasse Vorlage-Instanziierung "mpark::detail::copy_assignment<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<_Ty>>>,mpark::detail::Trait::Unavailable>", die kompiliert wird.
        with
        [
            _Ty=int
        ]
..\libs\variant\include\mpark/variant.hpp(1683): note: Siehe Verweis auf die Klasse Vorlage-Instanziierung "mpark::detail::impl<int,std::unique_ptr<int,std::default_delete<_Ty>>>", die kompiliert wird.
        with
        [
            _Ty=int
        ]
varianttest.cpp(7): note: Siehe Verweis auf die Klasse Vorlage-Instanziierung "mpark::variant<int,std::unique_ptr<int,std::default_delete<_Ty>>>", die kompiliert wird.
        with
        [
            _Ty=int
        ]
nightlark commented 5 years ago

For me, this is enough to reproduce it using the single-header variant (version 15.9.5):

#include "variant.hpp"

int main() {
    mpark::variant<int, std::unique_ptr<int>> var;
}

With these errors:

variant-msvc2017-bug-repro\variant.hpp(947): error C2131: expression did not evaluate to a constant
variant-msvc2017-bug-repro\variant.hpp(947): note: failure was caused by non-constant arguments or reference to a non-constant symbol
variant-msvc2017-bug-repro\variant.hpp(947): note: see usage of '$S4'
variant-msvc2017-bug-repro\variant.hpp(1948): note: see reference to class template instantiation 'mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<_Ty>>>' being compiled
        with
        [
            _Ty=int
        ]
variant-msvc2017-bug-repro\variant.hpp(2252): note: see reference to class template instantiation 'mpark::detail::impl<int,std::unique_ptr<int,std::default_delete<_Ty>>>' being compiled
        with
        [
            _Ty=int
        ]
variant-msvc2017-bug-repro\test.cpp(4): note: see reference to class template instantiation 'mpark::variant<int,std::unique_ptr<int,std::default_delete<_Ty>>>' being compiled
        with
        [
            _Ty=int
        ]
variant-msvc2017-bug-repro\variant.hpp(975): error C2131: expression did not evaluate to a constant
c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\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.16.27023\include\initializer_list(42): note: see usage of '$S3'
variant-msvc2017-bug-repro\variant.hpp(980): error C2131: expression did not evaluate to a constant
c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\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.16.27023\include\initializer_list(42): note: see usage of '$S5'
variant-msvc2017-bug-repro\variant.hpp(985): error C2131: expression did not evaluate to a constant
variant-msvc2017-bug-repro\variant.hpp(985): note: failure was caused by a read of an uninitialized symbol
variant-msvc2017-bug-repro\variant.hpp(985): note: see usage of 'copy_constructible_trait'
variant-msvc2017-bug-repro\variant.hpp(991): error C2131: expression did not evaluate to a constant
variant-msvc2017-bug-repro\variant.hpp(991): note: failure was caused by a read of an uninitialized symbol
variant-msvc2017-bug-repro\variant.hpp(991): note: see usage of 'move_constructible_trait'
variant-msvc2017-bug-repro\variant.hpp(997): error C2131: expression did not evaluate to a constant
c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\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.16.27023\include\initializer_list(42): note: see usage of '$S7'
variant-msvc2017-bug-repro\variant.hpp(1948): error C2975: 'unnamed-parameter': invalid template argument for 'mpark::detail::copy_assignment', expected compile-time constant expression
variant-msvc2017-bug-repro\variant.hpp(1910): note: see declaration of 'unnamed-parameter'
variant-msvc2017-bug-repro\variant.hpp(1948): error C2440: 'specialization': cannot convert from 'int' to 'mpark::detail::Trait'
variant-msvc2017-bug-repro\variant.hpp(1948): note: Conversion to enumeration type requires an explicit cast (static_cast, C-style cast or function-style cast)
variant-msvc2017-bug-repro\variant.hpp(1932): error C2975: 'unnamed-parameter': invalid template argument for 'mpark::detail::move_assignment', expected compile-time constant expression
variant-msvc2017-bug-repro\variant.hpp(1870): note: see declaration of 'unnamed-parameter'
variant-msvc2017-bug-repro\variant.hpp(1948): note: see reference to class template instantiation 'mpark::detail::copy_assignment<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<_Ty>>>,0>' being compiled
        with
        [
            _Ty=int
        ]
variant-msvc2017-bug-repro\variant.hpp(1932): error C2440: 'specialization': cannot convert from 'int' to 'mpark::detail::Trait'
variant-msvc2017-bug-repro\variant.hpp(1932): note: Conversion to enumeration type requires an explicit cast (static_cast, C-style cast or function-style cast)
variant-msvc2017-bug-repro\variant.hpp(1785): error C2975: 'unnamed-parameter': invalid template argument for 'mpark::detail::copy_constructor', expected compile-time constant expression
variant-msvc2017-bug-repro\variant.hpp(1747): note: see declaration of 'unnamed-parameter'
variant-msvc2017-bug-repro\variant.hpp(1892): note: see reference to class template instantiation 'mpark::detail::assignment<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<_Ty>>>>' being compiled
        with
        [
            _Ty=int
        ]
variant-msvc2017-bug-repro\variant.hpp(1932): note: see reference to class template instantiation 'mpark::detail::move_assignment<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<_Ty>>>,0>' being compiled
        with
        [
            _Ty=int
        ]
variant-msvc2017-bug-repro\variant.hpp(1785): error C2440: 'specialization': cannot convert from 'int' to 'mpark::detail::Trait'
variant-msvc2017-bug-repro\variant.hpp(1785): note: Conversion to enumeration type requires an explicit cast (static_cast, C-style cast or function-style cast)
variant-msvc2017-bug-repro\variant.hpp(1769): error C2975: 'unnamed-parameter': invalid template argument for 'mpark::detail::move_constructor', expected compile-time constant expression
variant-msvc2017-bug-repro\variant.hpp(1709): note: see declaration of 'unnamed-parameter'
variant-msvc2017-bug-repro\variant.hpp(1785): note: see reference to class template instantiation 'mpark::detail::copy_constructor<Traits,0>' being compiled
        with
        [
            Traits=mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<int>>>
        ]
variant-msvc2017-bug-repro\variant.hpp(1769): error C2440: 'specialization': cannot convert from 'int' to 'mpark::detail::Trait'
variant-msvc2017-bug-repro\variant.hpp(1769): note: Conversion to enumeration type requires an explicit cast (static_cast, C-style cast or function-style cast)
variant-msvc2017-bug-repro\variant.hpp(1662): error C2975: 'unnamed-parameter': invalid template argument for 'mpark::detail::destructor', expected compile-time constant expression
variant-msvc2017-bug-repro\variant.hpp(1614): note: see declaration of 'unnamed-parameter'
variant-msvc2017-bug-repro\variant.hpp(1731): note: see reference to class template instantiation 'mpark::detail::constructor<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<_Ty>>>>' being compiled
        with
        [
            _Ty=int
        ]
variant-msvc2017-bug-repro\variant.hpp(1769): note: see reference to class template instantiation 'mpark::detail::move_constructor<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<_Ty>>>,0>' being compiled
        with
        [
            _Ty=int
        ]
variant-msvc2017-bug-repro\variant.hpp(1662): error C2440: 'specialization': cannot convert from 'int' to 'mpark::detail::Trait'
variant-msvc2017-bug-repro\variant.hpp(1662): note: Conversion to enumeration type requires an explicit cast (static_cast, C-style cast or function-style cast)
variant-msvc2017-bug-repro\variant.hpp(1542): warning C4624: 'mpark::detail::recursive_union<mpark::detail::Trait::TriviallyAvailable,1,std::unique_ptr<int,std::default_delete<_Ty>>>': destructor was implicitly defined as deleted
        with
        [
            _Ty=int
        ]
variant-msvc2017-bug-repro\variant.hpp(1542): note: see reference to class template instantiation 'mpark::detail::recursive_union<mpark::detail::Trait::TriviallyAvailable,1,std::unique_ptr<int,std::default_delete<_Ty>>>' being compiled
        with
        [
            _Ty=int
        ]
variant-msvc2017-bug-repro\variant.hpp(1586): note: see reference to class template instantiation 'mpark::detail::recursive_union<mpark::detail::Trait::TriviallyAvailable,0,int,std::unique_ptr<int,std::default_delete<_Ty>>>' being compiled
        with
        [
            _Ty=int
        ]
variant-msvc2017-bug-repro\variant.hpp(1642): note: see reference to class template instantiation 'mpark::detail::base<mpark::detail::Trait::TriviallyAvailable,int,std::unique_ptr<int,std::default_delete<_Ty>>>' being compiled
        with
        [
            _Ty=int
        ]
variant-msvc2017-bug-repro\variant.hpp(1662): note: see reference to class template instantiation 'mpark::detail::destructor<Traits,0>' being compiled
        with
        [
            Traits=mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<int>>>
        ]
variant-msvc2017-bug-repro\variant.hpp(1542): warning C4624: 'mpark::detail::recursive_union<mpark::detail::Trait::TriviallyAvailable,0,int,std::unique_ptr<int,std::default_delete<_Ty>>>': destructor was implicitly defined as deleted
        with
        [
            _Ty=int
        ]
variant-msvc2017-bug-repro\variant.hpp(1591): warning C4624: 'mpark::detail::base<mpark::detail::Trait::TriviallyAvailable,int,std::unique_ptr<int,std::default_delete<_Ty>>>': destructor was implicitly defined as deleted
        with
        [
            _Ty=int
        ]
variant-msvc2017-bug-repro\variant.hpp(1642): warning C4624: 'mpark::detail::destructor<Traits,0>': destructor was implicitly defined as deleted
        with
        [
            Traits=mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<int>>>
        ]
variant-msvc2017-bug-repro\variant.hpp(1663): error C2975: 'unnamed-parameter': invalid template argument for 'mpark::detail::destructor', expected compile-time constant expression
variant-msvc2017-bug-repro\variant.hpp(1614): note: see declaration of 'unnamed-parameter'
variant-msvc2017-bug-repro\variant.hpp(1663): error C2440: 'specialization': cannot convert from 'int' to 'mpark::detail::Trait'
variant-msvc2017-bug-repro\variant.hpp(1663): note: Conversion to enumeration type requires an explicit cast (static_cast, C-style cast or function-style cast)
variant-msvc2017-bug-repro\variant.hpp(1707): warning C4624: 'mpark::detail::constructor<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<_Ty>>>>': destructor was implicitly defined as deleted
        with
        [
            _Ty=int
        ]
variant-msvc2017-bug-repro\variant.hpp(1731): warning C4624: 'mpark::detail::move_constructor<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<_Ty>>>,0>': destructor was implicitly defined as deleted
        with
        [
            _Ty=int
        ]
variant-msvc2017-bug-repro\variant.hpp(1769): warning C4624: 'mpark::detail::copy_constructor<Traits,0>': destructor was implicitly defined as deleted
        with
        [
            Traits=mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<int>>>
        ]
variant-msvc2017-bug-repro\variant.hpp(1786): error C2975: 'unnamed-parameter': invalid template argument for 'mpark::detail::copy_constructor', expected compile-time constant expression
variant-msvc2017-bug-repro\variant.hpp(1747): note: see declaration of 'unnamed-parameter'
variant-msvc2017-bug-repro\variant.hpp(1786): error C2440: 'specialization': cannot convert from 'int' to 'mpark::detail::Trait'
variant-msvc2017-bug-repro\variant.hpp(1786): note: Conversion to enumeration type requires an explicit cast (static_cast, C-style cast or function-style cast)
variant-msvc2017-bug-repro\variant.hpp(1868): warning C4624: 'mpark::detail::assignment<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<_Ty>>>>': destructor was implicitly defined as deleted
        with
        [
            _Ty=int
        ]
variant-msvc2017-bug-repro\variant.hpp(1892): warning C4624: 'mpark::detail::move_assignment<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<_Ty>>>,0>': destructor was implicitly defined as deleted
        with
        [
            _Ty=int
        ]
variant-msvc2017-bug-repro\variant.hpp(1932): warning C4624: 'mpark::detail::copy_assignment<mpark::detail::traits<int,std::unique_ptr<int,std::default_delete<_Ty>>>,0>': destructor was implicitly defined as deleted
        with
        [
            _Ty=int
        ]
variant-msvc2017-bug-repro\variant.hpp(1949): error C2975: 'unnamed-parameter': invalid template argument for 'mpark::detail::copy_assignment', expected compile-time constant expression
variant-msvc2017-bug-repro\variant.hpp(1910): note: see declaration of 'unnamed-parameter'
variant-msvc2017-bug-repro\variant.hpp(1949): error C2440: 'specialization': cannot convert from 'int' to 'mpark::detail::Trait'
variant-msvc2017-bug-repro\variant.hpp(1949): note: Conversion to enumeration type requires an explicit cast (static_cast, C-style cast or function-style cast)
variant-msvc2017-bug-repro\variant.hpp(2024): warning C4624: 'mpark::detail::impl<int,std::unique_ptr<int,std::default_delete<_Ty>>>': destructor was implicitly defined as deleted
        with
        [
            _Ty=int
        ]
variant-msvc2017-bug-repro\variant.hpp(2256): warning C4624: 'mpark::variant<int,std::unique_ptr<int,std::default_delete<_Ty>>>': destructor was implicitly defined as deleted
        with
        [
            _Ty=int
        ]
nightlark commented 5 years ago

I also tested with VS2019 preview 1.1 (version 16.0.0 preview 1.1, MSC_VER == 1920), and the same set of errors occur.

mgieseki commented 5 years ago

For me, this is enough to reproduce it using the single-header variant (version 15.9.5):

#include "variant.hpp"

int main() {
  mpark::variant<int, std::unique_ptr<int>> var;
}

Strange. For me, this example compiles without errors...

nightlark commented 5 years ago

It is odd -- I have a new laptop with a fresh install of Visual Studio 2017 and 2019 preview, no settings changed from the defaults.

mgieseki commented 5 years ago

Does your program actually include the latest single-header file from the master branch or is it perhaps an older version? At first glance, the error messages and line numbers don't seem to match the statements in variant.hpp at the corresponding positions.

nightlark commented 5 years ago

I'll update it with the log from the latest variant.hpp. I realized I might have been using an older version (of variant.hpp) before posting the log, so I updated variant.hpp and still got the same set of errors so I just posted the old log -- which is why the line numbers are off.

mpark commented 5 years ago

On master, with Microsoft (R) C/C++ Optimizing Compiler Version 19.16.27026.1 for x86:

For me, this is enough to reproduce it using the single-header variant (version 15.9.5):

include "variant.hpp"

int main() {
  mpark::variant<int, std::unique_ptr<int>> var;
}

This compiles fine for me.


#include <mpark/variant.hpp>
#include <memory>
#include <vector>

struct S {
  S (int n) : var(n) {}
  mpark::variant<int, std::unique_ptr<int>> var;
};

int main () {
  std::vector<S> vec;
  vec.emplace_back(0);
}

This does not. But this doesn't pass even after applying this patch 😕

nightlark commented 5 years ago

I should probably get the 19.x version number of the compiler for comparison, since it seems odd that you aren’t getting errors — maybe a different optimization level flag? I guess the thing to do would be to try reproducing the errors in a VM, since each of us seems to be seeing different behavior.

mgieseki commented 5 years ago

I can confirm @mpark's summary. It's the exact same behavior on my machine. Obviously, my example triggers an issue that's unrelated to this PR. It was introduced by commit 62b41fea0bcb7e32f28ab312b362b17c11b884e3.

BTW, my MSVC version is 19.16.27026.1 and I call cl on the command line without any options except /I to specify the include path.

mpark commented 5 years ago

I've added @mgieseki's example as a test case in b68278366135ef69cc0614d7a76e4b761cc31c8b, fixed the issue that it was running into in 8cab6363d4580c9c1990a083514189916a6be125, and addressed the root cause of the MPARK_CPP14_CONSTEXPR related issue in 19.15 in 657110d5ea11f344d29bce1d9609c7d76696cb64.

Please let me know if there are remaining problems!

nightlark commented 5 years ago

Awesome! Thanks @mpark, with those changes it now compiles with MSVC 2017 and 2019 preview. Seems like compiler bugs are a bit of a theme with the MSVC compilers.