10373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier// -*- C++ -*-
20373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier//===----------------------------------------------------------------------===//
30373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier//
40373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier//                     The LLVM Compiler Infrastructure
50373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier//
60373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier// This file is dual licensed under the MIT and the University of Illinois Open
70373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier// Source Licenses. See LICENSE.TXT for details.
80373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier//
90373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier//===----------------------------------------------------------------------===//
100373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
110373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier// UNSUPPORTED: c++98, c++03, c++11, c++14
120373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
130373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier// <variant>
140373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
150373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier// template <class ...Types> class variant;
160373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
170373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier// template <size_t I, class U, class ...Args>
180373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier// void emplace(initializer_list<U> il,Args&&... args);
190373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
200373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#include <cassert>
210373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#include <string>
220373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#include <type_traits>
230373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#include <variant>
240373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
250373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#include "archetypes.hpp"
260373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#include "test_convertible.hpp"
270373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier#include "test_macros.h"
280373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
290373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselierstruct InitList {
300373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  std::size_t size;
310373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  constexpr InitList(std::initializer_list<int> il) : size(il.size()) {}
320373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier};
330373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
340373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselierstruct InitListArg {
350373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  std::size_t size;
360373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  int value;
370373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  constexpr InitListArg(std::initializer_list<int> il, int v)
380373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier      : size(il.size()), value(v) {}
390373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier};
400373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
410373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiseliertemplate <class Var, size_t I, class... Args>
420373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselierconstexpr auto test_emplace_exists_imp(int) -> decltype(
430373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier    std::declval<Var>().template emplace<I>(std::declval<Args>()...), true) {
440373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  return true;
450373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier}
460373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
470373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiseliertemplate <class, size_t, class...>
480373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselierconstexpr auto test_emplace_exists_imp(long) -> bool {
490373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  return false;
500373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier}
510373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
520373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiseliertemplate <class Var, size_t I, class... Args> constexpr bool emplace_exists() {
530373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  return test_emplace_exists_imp<Var, I, Args...>(0);
540373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier}
550373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
560373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiseliervoid test_emplace_sfinae() {
570373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  using V =
580373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier      std::variant<int, TestTypes::NoCtors, InitList, InitListArg, long, long>;
590373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  using IL = std::initializer_list<int>;
600373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  static_assert(!emplace_exists<V, 1, IL>(), "no such constructor");
610373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  static_assert(emplace_exists<V, 2, IL>(), "");
620373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  static_assert(!emplace_exists<V, 2, int>(), "args don't match");
630373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  static_assert(!emplace_exists<V, 2, IL, int>(), "too many args");
640373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  static_assert(emplace_exists<V, 3, IL, int>(), "");
650373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  static_assert(!emplace_exists<V, 3, int>(), "args don't match");
660373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  static_assert(!emplace_exists<V, 3, IL>(), "too few args");
670373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  static_assert(!emplace_exists<V, 3, IL, int, int>(), "too many args");
680373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier}
690373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
700373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiseliervoid test_basic() {
710373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  using V = std::variant<int, InitList, InitListArg, TestTypes::NoCtors>;
720373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  V v;
730373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  v.emplace<1>({1, 2, 3});
740373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  assert(std::get<1>(v).size == 3);
750373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  v.emplace<2>({1, 2, 3, 4}, 42);
760373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  assert(std::get<2>(v).size == 4);
770373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  assert(std::get<2>(v).value == 42);
780373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  v.emplace<1>({1});
790373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  assert(std::get<1>(v).size == 1);
800373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier}
810373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier
820373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselierint main() {
830373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  test_basic();
840373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier  test_emplace_sfinae();
850373708cdc6b84bcfac38f4cf8539c6dd794d360Eric Fiselier}
86