1 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
2 // https://github.com/Dobiasd/FunctionalPlus
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at
5 //  http://www.boost.org/LICENSE_1_0.txt)
6 
7 #include <doctest/doctest.h>
8 #include <fplus/fplus.hpp>
9 
10 namespace {
11     std::string print_output;
12 
print_int(int x)13     bool print_int(int x)
14     {
15         print_output = "int " + std::to_string(x);
16         return true;
17     }
18 
print_double(double x)19     bool print_double(double x)
20     {
21         print_output = "double " + std::to_string(fplus::round(x));
22         return true;
23     }
24 
print_string(const std::string & str)25     bool print_string(const std::string& str)
26     {
27         print_output = "string " + str;
28         return true;
29     }
30 
show_int(int x)31     std::string show_int(int x)
32     {
33         return fplus::show(x);
34     }
35 
show_string(const std::string & str)36     std::string show_string(const std::string& str)
37     {
38         return fplus::show(str);
39     }
40 }
41 
42 TEST_CASE("variant_test - visit_one")
43 {
44     using namespace fplus;
45 
46     fplus::variant<int, double> int_or_double(3);
47 
48     int_or_double.visit_one(print_int);
49     REQUIRE_EQ(print_output, "int 3");
50     print_output.clear();
51 
52     int_or_double.visit_one(print_double);
53     REQUIRE_EQ(print_output, "");
54     print_output.clear();
55 
56     int_or_double = 23.0;
57 
58     int_or_double.visit_one(print_int);
59     REQUIRE_EQ(print_output, "");
60     print_output.clear();
61 
62     int_or_double.visit_one(print_double);
63     REQUIRE_EQ(print_output, "double 23");
64     print_output.clear();
65 
66 
67     using float_or_double = fplus::variant<float, double>;
68     using nested = fplus::variant<int, float_or_double>;
69     nested int_or_float_double_variant(fplus::variant<float, double>(3.0));
70 
71     const auto print_nested_double = [&](const float_or_double& f_o_d) -> int
__anon171960ca0202(const float_or_double& f_o_d) 72     {
73         f_o_d.visit_one(print_double);
74         return 0;
75     };
76 
77     int_or_float_double_variant.visit_one(print_nested_double);
78     REQUIRE_EQ(print_output, "double 3");
79     print_output.clear();
80 }
81 
82 TEST_CASE("variant_test - equality_test")
83 {
84     using namespace fplus;
85     fplus::variant<int, std::string> int_or_string_i(3);
86     fplus::variant<int, std::string> int_or_string_s(std::string("hi"));
87     REQUIRE(int_or_string_i == int_or_string_i);
88     REQUIRE_FALSE(int_or_string_i == int_or_string_s);
89 }
90 
91 TEST_CASE("variant_test - inequality_test")
92 {
93     using namespace fplus;
94     fplus::variant<int, std::string> int_or_string_i(3);
95     fplus::variant<int, std::string> int_or_string_s(std::string("hi"));
96     REQUIRE_FALSE(int_or_string_i != int_or_string_i);
97     REQUIRE(int_or_string_i != int_or_string_s);
98 }
99 
100 TEST_CASE("variant_test - visit")
101 {
102     using namespace fplus;
103 
104     // should not compile
105     //int_or_double.visit_one<std::string>(print_string);
106 
107     fplus::variant<int, std::string> int_or_string(3);
108 
109     REQUIRE(int_or_string.is<int>());
110     REQUIRE_FALSE(int_or_string.is<std::string>());
111 
112     int_or_string.visit(print_int, print_string);
113     REQUIRE_EQ(print_output, "int 3");
114     print_output.clear();
115 
116     const auto transform_result =
117         int_or_string.transform(show_int, show_string);
118     transform_result.visit_one(print_string);
119     REQUIRE_EQ(print_output, "string 3");
120     print_output.clear();
121 
122     // should not compile
123     //std::cout << int_or_string.visit(show_int, show_float) << std::endl;
124 
125     // should not compile
126     //std::cout << int_or_string.visit(show_int, show_int) << std::endl;
127 
128     // should not compile
129     //std::cout << int_or_string.visit(show_int, show_string, show_double) << std::endl;
130 
131     // should not compile
132     //std::cout << int_or_string.visit(show_int) << std::endl;
133 }
134