#include <variant> #include <stdio.h> struct none { none() = delete; }; struct any { template <typename T> any(T&&) {} }; int main() { std::variant<none, any> v(std::in_place_type<none>); std::variant<none, any> v2(std::in_place_index<0>); printf("constructed alternatives %zu and %zu\n", v.index(), v2.index()); } This program should be ill-formed, but instead compiles and outputs: constructed alternatives 1 and 1
The variant(T&&) constructor is being selected by overload resolution, because we talk to apply this constraint: remove_cvref_t<T> is neither a specialization of in_place_type_t nor a specialization of in_place_index_t,
(In reply to Jonathan Wakely from comment #1) > because we talk to apply this constraint: s/talk/fail/
Author: redi Date: Tue Apr 23 12:48:18 2019 New Revision: 270509 URL: https://gcc.gnu.org/viewcvs?rev=270509&root=gcc&view=rev Log: PR libstdc++/90165 constrain variant(T&&) constructor Also refactor some constraints slightly to be more readable. PR libstdc++/90165 * include/std/variant (variant::__not_self): New helper for the is_same_v<remove_cvref_t<T>, variant>==false constraints. (variant::__to_type_impl): Remove. (variant::__to_type): Add default argument to check pack size, instead of using __to_type_impl. (variant::__accepted_type): Add default argument using __not_self. (variant::__is_in_place_tag, variant::__not_in_place_tag): New helpers for variant(T&&) constructor constraint. (variant::variant(T&&)): Use __not_in_place_tag in constraints. Extract __accepted_type into a named template parameter for reuse in other constraints and in the exception specification. (variant::variant(in_place_type_t<T>, Args&&...)) (variant::variant(in_place_type_t<T>, initializer_list<U>, Args&&...)) (variant::variant(in_place_index_t<T>, Args&&...)) (variant::variant(in_place_index_t<T>, initializer_list<U>, Args&&...)) (variant::operator=T&&)): Remove redundant && from trait arguments. * testsuite/20_util/variant/compile.cc: Check variant(T&&) constructor isn't used for in_place_type or in_place_index arguments. Modified: trunk/libstdc++-v3/ChangeLog trunk/libstdc++-v3/include/std/variant trunk/libstdc++-v3/testsuite/20_util/variant/compile.cc
Fixed on trunk so far.
Author: redi Date: Tue May 7 15:46:36 2019 New Revision: 270966 URL: https://gcc.gnu.org/viewcvs?rev=270966&root=gcc&view=rev Log: PR libstdc++/90165 constrain variant(T&&) constructor Backport from mainline 2019-04-23 Jonathan Wakely <jwakely@redhat.com> PR libstdc++/90165 * include/std/variant (variant::__is_in_place_tag) (variant::__not_in_place_tag): New helpers for variant(T&&) constructor constraint. (variant::variant(T&&)): Use __not_in_place_tag in constraints. * testsuite/20_util/variant/compile.cc: Check variant(T&&) constructor isn't used for in_place_type or in_place_index arguments. Modified: branches/gcc-8-branch/libstdc++-v3/ChangeLog branches/gcc-8-branch/libstdc++-v3/include/std/variant branches/gcc-8-branch/libstdc++-v3/testsuite/20_util/variant/compile.cc
Fixed for 8.4 too.