为 std::variant 提供一个运算符==
Provide a operator== for std::variant
我正在尝试为映射中定义的 std::variant
创建一个 operator==
运算符,如下所示:
struct anyType
{
template<typename T>
void operator()(T t) const { std::cout << t; }
void operator()(const std::string& s) const { std::cout << '\"' << s << '\"'; }
};
template<typename T>
bool operator==(const std::variant<float, int, bool, std::string>& v, const& T t)
{
return v == t;
}
int main()
{
std::map<std::string, std::variant<float, int, bool, std::string>> kwargs;
kwargs["interface"] = "linear"s;
kwargs["flag"] = true;
kwargs["height"] = 5;
kwargs["length"] = 6;
//test
if (kwarg["interface"] == "linear") // stack overflow Error here
{
std::cout << true << '\n';
}
else
{
std::cout << false << '\n';
}
}
谁能告诉我为什么接线员不工作?
您的代码中有几个问题:
const &T t
在你的 operator==
中,应该是 T const& t
或 const T& t
.
你忘了说你想和a比较
std::string
不与 if 语句中的 char
数组一起使用(即 "linear"
)。意思是你
需要以下之一:
if (kwargs["interface"] == std::string{ "linear" })
// or
using namespace std::string_literals;
if (kwargs["interface"] == "linear"s) // since C++14
当你这样比较的时候
if (kwargs["interface"] == "linear") // checking std::variant == char [7]
您正在检查类型为 char [7]
(即 linear
的类型)的 std::variant<float, int, bool, std::string>
(即 v
)。
当条件达到 operator==
的定义时,你再做一次
同
return v == t; // checking std::variant == char [7]
这导致递归调用模板 operator==
本身
因此堆栈溢出。
为了修复,您需要strong text 通过索引或类型明确指定变体的值。例如,检查类型使用 std::is_same
and if constexpr
:
#include <type_traits> std::is_same_v
template<typename T>
bool operator==(const std::variant<float, int, bool, std::string>& v, T const& t)
{
if constexpr (std::is_same_v<T, float>) // float
return std::get<float>(v) == t;
else if constexpr (std::is_same_v<T, int>) // int
return std::get<int>(v) == t;
else if constexpr (std::is_same_v<T, bool>) // boolean
return std::get<bool>(v) == t;
else if constexpr (std::is_same_v<T, std::string>) // std::string
return std::get<std::string>(v) == t;
}
或简单地 (Credits @Barry)
template<typename T>
bool operator==(const std::variant<float, int, bool, std::string>& v, T const& t)
{
return std::get<T>(v) == t;
}
现在,如果您传递 v
以外的任何其他类型包含,您将收到模板化 operator==
.
的编译时错误
通用解决方案!
对于泛型std::varaint<Types...>
,可以按如下方式进行。另外,已经SFINAE d for only those types which are in the passed std::variant<Types>
. I have used the .
#include <variant>
#include <type_traits>
// A trait to check that T is one of 'Types...'
template <typename T, typename...Types>
struct is_one_of final : std::disjunction<std::is_same<T, Types>...> {};
template<typename... Types, typename T>
auto operator==(const std::variant<Types...>& v, T const& t) noexcept
-> std::enable_if_t<is_one_of<T, Types...>::value, bool>
{
return std::get<T>(v) == t;
}
我正在尝试为映射中定义的 std::variant
创建一个 operator==
运算符,如下所示:
struct anyType
{
template<typename T>
void operator()(T t) const { std::cout << t; }
void operator()(const std::string& s) const { std::cout << '\"' << s << '\"'; }
};
template<typename T>
bool operator==(const std::variant<float, int, bool, std::string>& v, const& T t)
{
return v == t;
}
int main()
{
std::map<std::string, std::variant<float, int, bool, std::string>> kwargs;
kwargs["interface"] = "linear"s;
kwargs["flag"] = true;
kwargs["height"] = 5;
kwargs["length"] = 6;
//test
if (kwarg["interface"] == "linear") // stack overflow Error here
{
std::cout << true << '\n';
}
else
{
std::cout << false << '\n';
}
}
谁能告诉我为什么接线员不工作?
您的代码中有几个问题:
const &T t
在你的operator==
中,应该是T const& t
或const T& t
.你忘了说你想和a比较
std::string
不与 if 语句中的char
数组一起使用(即"linear"
)。意思是你 需要以下之一:if (kwargs["interface"] == std::string{ "linear" }) // or using namespace std::string_literals; if (kwargs["interface"] == "linear"s) // since C++14
当你这样比较的时候
if (kwargs["interface"] == "linear") // checking std::variant == char [7]
您正在检查类型为
char [7]
(即linear
的类型)的std::variant<float, int, bool, std::string>
(即v
)。 当条件达到operator==
的定义时,你再做一次 同return v == t; // checking std::variant == char [7]
这导致递归调用模板
operator==
本身 因此堆栈溢出。
为了修复,您需要strong text 通过索引或类型明确指定变体的值。例如,检查类型使用 std::is_same
and if constexpr
:
#include <type_traits> std::is_same_v
template<typename T>
bool operator==(const std::variant<float, int, bool, std::string>& v, T const& t)
{
if constexpr (std::is_same_v<T, float>) // float
return std::get<float>(v) == t;
else if constexpr (std::is_same_v<T, int>) // int
return std::get<int>(v) == t;
else if constexpr (std::is_same_v<T, bool>) // boolean
return std::get<bool>(v) == t;
else if constexpr (std::is_same_v<T, std::string>) // std::string
return std::get<std::string>(v) == t;
}
或简单地 (Credits @Barry)
template<typename T>
bool operator==(const std::variant<float, int, bool, std::string>& v, T const& t)
{
return std::get<T>(v) == t;
}
现在,如果您传递 v
以外的任何其他类型包含,您将收到模板化 operator==
.
通用解决方案!
对于泛型std::varaint<Types...>
,可以按如下方式进行。另外,已经SFINAE d for only those types which are in the passed std::variant<Types>
. I have used the
#include <variant>
#include <type_traits>
// A trait to check that T is one of 'Types...'
template <typename T, typename...Types>
struct is_one_of final : std::disjunction<std::is_same<T, Types>...> {};
template<typename... Types, typename T>
auto operator==(const std::variant<Types...>& v, T const& t) noexcept
-> std::enable_if_t<is_one_of<T, Types...>::value, bool>
{
return std::get<T>(v) == t;
}