Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 676e551

Browse files
committed
Use std::visit to exhaust std::variant possibilities.
This makes it unnecessary to silence impossible "unhandled" cases.
1 parent a0fb5cf commit 676e551

3 files changed

Lines changed: 105 additions & 125 deletions

File tree

src/_backend_agg_wrapper.cpp

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -63,31 +63,30 @@ PyRendererAgg_draw_text_image(RendererAgg *self,
6363
double angle,
6464
GCAgg &gc)
6565
{
66-
int x, y;
67-
68-
if (auto value = std::get_if<double>(&vx)) {
69-
auto api = py::module_::import("matplotlib._api");
70-
auto warn = api.attr("warn_deprecated");
71-
warn("since"_a="3.10", "name"_a="x", "obj_type"_a="parameter as float",
72-
"alternative"_a="int(x)");
73-
x = static_cast<int>(*value);
74-
} else if (auto value = std::get_if<int>(&vx)) {
75-
x = *value;
76-
} else {
77-
throw std::runtime_error("Should not happen");
78-
}
79-
80-
if (auto value = std::get_if<double>(&vy)) {
81-
auto api = py::module_::import("matplotlib._api");
82-
auto warn = api.attr("warn_deprecated");
83-
warn("since"_a="3.10", "name"_a="y", "obj_type"_a="parameter as float",
84-
"alternative"_a="int(y)");
85-
y = static_cast<int>(*value);
86-
} else if (auto value = std::get_if<int>(&vy)) {
87-
y = *value;
88-
} else {
89-
throw std::runtime_error("Should not happen");
90-
}
66+
int x = std::visit(overloaded {
67+
[&](double value) {
68+
auto api = py::module_::import("matplotlib._api");
69+
auto warn = api.attr("warn_deprecated");
70+
warn("since"_a="3.10", "name"_a="x", "obj_type"_a="parameter as float",
71+
"alternative"_a="int(x)");
72+
return static_cast<int>(value);
73+
},
74+
[](int value) {
75+
return value;
76+
}
77+
}, vx);
78+
int y = std::visit(overloaded {
79+
[&](double value) {
80+
auto api = py::module_::import("matplotlib._api");
81+
auto warn = api.attr("warn_deprecated");
82+
warn("since"_a="3.10", "name"_a="y", "obj_type"_a="parameter as float",
83+
"alternative"_a="int(x)");
84+
return static_cast<int>(value);
85+
},
86+
[](int value) {
87+
return value;
88+
}
89+
}, vy);
9190

9291
// TODO: This really shouldn't be mutable, but Agg's renderer buffers aren't const.
9392
auto image = image_obj.mutable_unchecked<2>();

src/ft2font_wrapper.cpp

Lines changed: 72 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <pybind11/stl.h>
55

66
#include "ft2font.h"
7+
#include "mplutils.h"
78
#include "_enums.h"
89

910
#include <set>
@@ -18,23 +19,20 @@ using double_or_ = std::variant<double, T>;
1819

1920
template <typename T>
2021
static T
21-
_double_to_(const char *name, double_or_<T> &var)
22+
_double_to_(const char *name, double_or_<T> var)
2223
{
23-
if (auto value = std::get_if<double>(&var)) {
24-
auto api = py::module_::import("matplotlib._api");
25-
auto warn = api.attr("warn_deprecated");
26-
warn("since"_a="3.10", "name"_a=name, "obj_type"_a="parameter as float",
27-
"alternative"_a="int({})"_s.format(name));
28-
return static_cast<T>(*value);
29-
} else if (auto value = std::get_if<T>(&var)) {
30-
return *value;
31-
} else {
32-
// pybind11 will have only allowed types that match the variant, so this `else`
33-
// can't happen. We only have this case because older macOS doesn't support
34-
// `std::get` and using the conditional `std::get_if` means an `else` to silence
35-
// compiler warnings about "unhandled" cases.
36-
throw std::runtime_error("Should not happen");
37-
}
24+
return std::visit(overloaded {
25+
[&](double value) {
26+
auto api = py::module_::import("matplotlib._api");
27+
auto warn = api.attr("warn_deprecated");
28+
warn("since"_a="3.10", "name"_a=name, "obj_type"_a="parameter as float",
29+
"alternative"_a="int({})"_s.format(name));
30+
return static_cast<T>(value);
31+
},
32+
[](T value) {
33+
return value;
34+
}
35+
}, var);
3836
}
3937

4038
/**********************************************************************
@@ -603,22 +601,18 @@ static int
603601
PyFT2Font_get_kerning(PyFT2Font *self, FT_UInt left, FT_UInt right,
604602
std::variant<FT_Kerning_Mode, FT_UInt> mode_or_int)
605603
{
606-
FT_Kerning_Mode mode;
607-
608-
if (auto value = std::get_if<FT_UInt>(&mode_or_int)) {
609-
auto api = py::module_::import("matplotlib._api");
610-
auto warn = api.attr("warn_deprecated");
611-
warn("since"_a="3.10", "name"_a="mode", "obj_type"_a="parameter as int",
612-
"alternative"_a="Kerning enum values");
613-
mode = static_cast<FT_Kerning_Mode>(*value);
614-
} else if (auto value = std::get_if<FT_Kerning_Mode>(&mode_or_int)) {
615-
mode = *value;
616-
} else {
617-
// NOTE: this can never happen as pybind11 would have checked the type in the
618-
// Python wrapper before calling this function, but we need to keep the
619-
// std::get_if instead of std::get for macOS 10.12 compatibility.
620-
throw py::type_error("mode must be Kerning or int");
621-
}
604+
FT_Kerning_Mode mode = std::visit(overloaded {
605+
[&](FT_UInt value) {
606+
auto api = py::module_::import("matplotlib._api");
607+
auto warn = api.attr("warn_deprecated");
608+
warn("since"_a="3.10", "name"_a="mode", "obj_type"_a="parameter as int",
609+
"alternative"_a="Kerning enum values");
610+
return static_cast<FT_Kerning_Mode>(value);
611+
},
612+
[](FT_Kerning_Mode value) {
613+
return value;
614+
}
615+
}, mode_or_int);
622616

623617
return self->get_kerning(left, right, mode);
624618
}
@@ -708,36 +702,28 @@ PyFT2Font_set_text(PyFT2Font *self, std::u32string_view text, double angle = 0.0
708702
std::variant<FT2Font::LanguageType, std::string> languages_or_str = nullptr)
709703
{
710704
std::vector<double> xys;
711-
LoadFlags flags;
712-
713-
if (auto value = std::get_if<FT_Int32>(&flags_or_int)) {
714-
auto api = py::module_::import("matplotlib._api");
715-
auto warn = api.attr("warn_deprecated");
716-
warn("since"_a="3.10", "name"_a="flags", "obj_type"_a="parameter as int",
717-
"alternative"_a="LoadFlags enum values");
718-
flags = static_cast<LoadFlags>(*value);
719-
} else if (auto value = std::get_if<LoadFlags>(&flags_or_int)) {
720-
flags = *value;
721-
} else {
722-
// NOTE: this can never happen as pybind11 would have checked the type in the
723-
// Python wrapper before calling this function, but we need to keep the
724-
// std::get_if instead of std::get for macOS 10.12 compatibility.
725-
throw py::type_error("flags must be LoadFlags or int");
726-
}
727-
728-
FT2Font::LanguageType languages;
729-
if (auto value = std::get_if<FT2Font::LanguageType>(&languages_or_str)) {
730-
languages = std::move(*value);
731-
} else if (auto value = std::get_if<std::string>(&languages_or_str)) {
732-
languages = std::vector<FT2Font::LanguageRange>{
733-
FT2Font::LanguageRange{*value, 0, text.size()}
734-
};
735-
} else {
736-
// NOTE: this can never happen as pybind11 would have checked the type in the
737-
// Python wrapper before calling this function, but we need to keep the
738-
// std::get_if instead of std::get for macOS 10.12 compatibility.
739-
throw py::type_error("languages must be str or list of tuple");
740-
}
705+
LoadFlags flags = std::visit(overloaded {
706+
[&](FT_Int32 value) {
707+
auto api = py::module_::import("matplotlib._api");
708+
auto warn = api.attr("warn_deprecated");
709+
warn("since"_a="3.10", "name"_a="flags", "obj_type"_a="parameter as int",
710+
"alternative"_a="LoadFlags enum values");
711+
return static_cast<LoadFlags>(value);
712+
},
713+
[](LoadFlags value) {
714+
return value;
715+
}
716+
}, flags_or_int);
717+
718+
FT2Font::LanguageType languages = std::visit(overloaded {
719+
[](FT2Font::LanguageType languages) {
720+
return languages;
721+
},
722+
[&](std::string value) {
723+
return FT2Font::LanguageType{{
724+
FT2Font::LanguageRange{value, 0, text.size()}}};
725+
}
726+
}, languages_or_str);
741727

742728
self->set_text(text, angle, static_cast<FT_Int32>(flags), features, languages, xys);
743729

@@ -783,22 +769,18 @@ PyFT2Font_load_char(PyFT2Font *self, long charcode,
783769
{
784770
bool fallback = true;
785771
FT2Font *ft_object = nullptr;
786-
LoadFlags flags;
787-
788-
if (auto value = std::get_if<FT_Int32>(&flags_or_int)) {
789-
auto api = py::module_::import("matplotlib._api");
790-
auto warn = api.attr("warn_deprecated");
791-
warn("since"_a="3.10", "name"_a="flags", "obj_type"_a="parameter as int",
792-
"alternative"_a="LoadFlags enum values");
793-
flags = static_cast<LoadFlags>(*value);
794-
} else if (auto value = std::get_if<LoadFlags>(&flags_or_int)) {
795-
flags = *value;
796-
} else {
797-
// NOTE: this can never happen as pybind11 would have checked the type in the
798-
// Python wrapper before calling this function, but we need to keep the
799-
// std::get_if instead of std::get for macOS 10.12 compatibility.
800-
throw py::type_error("flags must be LoadFlags or int");
801-
}
772+
LoadFlags flags = std::visit(overloaded {
773+
[&](FT_Int32 value) {
774+
auto api = py::module_::import("matplotlib._api");
775+
auto warn = api.attr("warn_deprecated");
776+
warn("since"_a="3.10", "name"_a="flags", "obj_type"_a="parameter as int",
777+
"alternative"_a="LoadFlags enum values");
778+
return static_cast<LoadFlags>(value);
779+
},
780+
[](LoadFlags value) {
781+
return value;
782+
}
783+
}, flags_or_int);
802784

803785
self->load_char(charcode, static_cast<FT_Int32>(flags), ft_object, fallback);
804786

@@ -835,22 +817,18 @@ static PyGlyph *
835817
PyFT2Font_load_glyph(PyFT2Font *self, FT_UInt glyph_index,
836818
std::variant<LoadFlags, FT_Int32> flags_or_int = LoadFlags::FORCE_AUTOHINT)
837819
{
838-
LoadFlags flags;
839-
840-
if (auto value = std::get_if<FT_Int32>(&flags_or_int)) {
841-
auto api = py::module_::import("matplotlib._api");
842-
auto warn = api.attr("warn_deprecated");
843-
warn("since"_a="3.10", "name"_a="flags", "obj_type"_a="parameter as int",
844-
"alternative"_a="LoadFlags enum values");
845-
flags = static_cast<LoadFlags>(*value);
846-
} else if (auto value = std::get_if<LoadFlags>(&flags_or_int)) {
847-
flags = *value;
848-
} else {
849-
// NOTE: this can never happen as pybind11 would have checked the type in the
850-
// Python wrapper before calling this function, but we need to keep the
851-
// std::get_if instead of std::get for macOS 10.12 compatibility.
852-
throw py::type_error("flags must be LoadFlags or int");
853-
}
820+
LoadFlags flags = std::visit(overloaded {
821+
[&](FT_Int32 value) {
822+
auto api = py::module_::import("matplotlib._api");
823+
auto warn = api.attr("warn_deprecated");
824+
warn("since"_a="3.10", "name"_a="flags", "obj_type"_a="parameter as int",
825+
"alternative"_a="LoadFlags enum values");
826+
return static_cast<LoadFlags>(value);
827+
},
828+
[](LoadFlags value) {
829+
return value;
830+
}
831+
}, flags_or_int);
854832

855833
self->load_glyph(glyph_index, static_cast<FT_Int32>(flags));
856834

src/mplutils.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,18 @@ enum {
4949
};
5050

5151
#ifdef __cplusplus // not for macosx.m
52-
// Check that array has shape (N, d1) or (N, d1, d2). We cast d1, d2 to longs
53-
// so that we don't need to access the NPY_INTP_FMT macro here.
5452
#include <pybind11/pybind11.h>
5553
#include <pybind11/numpy.h>
5654

5755
namespace py = pybind11;
5856
using namespace pybind11::literals;
5957

58+
// Helper for std::visit.
59+
template<typename... Ts> struct overloaded : Ts... { using Ts::operator()...; };
60+
template<typename... Ts> overloaded(Ts...) -> overloaded<Ts...>;
61+
62+
// Check that array has shape (N, d1) or (N, d1, d2). We cast d1, d2 to longs
63+
// so that we don't need to access the NPY_INTP_FMT macro here.
6064
template<typename T>
6165
inline void check_trailing_shape(T array, char const* name, long d1)
6266
{
@@ -95,11 +99,10 @@ inline void check_trailing_shape(T array, char const* name, long d1, long d2)
9599
}
96100
}
97101

98-
/* In most cases, code should use safe_first_shape(obj) instead of obj.shape(0), since
99-
safe_first_shape(obj) == 0 when any dimension is 0. */
102+
// In most cases, code should use safe_first_shape(obj) instead of
103+
// obj.shape(0), since safe_first_shape(obj) == 0 when any dimension is 0.
100104
template <typename T, py::ssize_t ND>
101-
py::ssize_t
102-
safe_first_shape(const py::detail::unchecked_reference<T, ND> &a)
105+
py::ssize_t safe_first_shape(const py::detail::unchecked_reference<T, ND> &a)
103106
{
104107
bool empty = (ND == 0);
105108
for (py::ssize_t i = 0; i < ND; i++) {

0 commit comments

Comments
 (0)