Files
carbon-lang/toolchain/base/kind_switch_test.cpp
T
Dana JansensandRichard Smith b24944bfba Allow using CARBON_KIND_SWITCH on a std::variant (#5433)
We use CARBON_KIND_SWITCH for handling the output of TypeIterator in the
TypeStructureBuilder

Here is how the errors look when it is misused:
- If you don't cover ever type in the variant with a case
  ```
Enumeration value 'VariantTypeT1NotHandledInSwitch' not handled in
switch
  ```
Is attached to the CARBON_KIND_SWITCH() usage, the `T1` being a 0-based
index into the std::variant's type list, indicating which type was
missed.
- If you have a case for a type that is not in the variant
  ```
In template: constraints not satisfied for class template
'ValidCaseType' [with T = char]
  ... bunch of instantiation stuff ...
kind_switch.h(124, 12): Because 'char' does not satisfy
'TypeFoundInVariant'
  ```
Where `char` was the type I put in the `CARBON_KIND` macro, which was
not in the variant.
- If you have too many types in your variant (currently > 12)
  ```
In template: static assertion failed due to requirement 'sizeof...(Ts)
<= 12': CARBON_KIND_SWITCH supports std::variant with up to 12 types.
Add more if needed.
  ```
  Is attached to the CARBON_KIND_SWITCH() usage.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2025-05-12 16:26:55 +00:00

58 lines
1.4 KiB
C++

// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include "toolchain/base/kind_switch.h"
#include <gtest/gtest.h>
#include <string>
#include <variant>
#include "common/raw_string_ostream.h"
namespace Carbon {
namespace {
TEST(KindSwitch, Variant) {
auto f = [](std::variant<int, float, char> v) -> std::string {
RawStringOstream str;
CARBON_KIND_SWITCH(v) {
case CARBON_KIND(int n):
str << "int = " << n;
return str.TakeStr();
case CARBON_KIND(float f):
str << "float = " << f;
return str.TakeStr();
case CARBON_KIND(char c):
str << "char = " << c;
return str.TakeStr();
}
};
EXPECT_EQ(f(int{1}), "int = 1");
EXPECT_EQ(f(float{2}), "float = 2.000000e+00");
EXPECT_EQ(f(char{'h'}), "char = h");
}
TEST(KindSwitch, VariantUnusedValue) {
auto f = [](std::variant<int, float> v) -> std::string {
RawStringOstream str;
CARBON_KIND_SWITCH(v) {
case CARBON_KIND(int n):
str << "int = " << n;
return str.TakeStr();
case CARBON_KIND(float _):
// The float value is not used, we see that using `_` works.
str << "float";
return str.TakeStr();
}
};
EXPECT_EQ(f(int{1}), "int = 1");
EXPECT_EQ(f(float{2}), "float");
}
} // namespace
} // namespace Carbon