c++ - 为 std::variant 提供 operator==
问题描述
我正在尝试为地图中定义的运算符创建一个operator==
运算符,std::variant
如下所示:
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
。您忘记提及您想 在 if 语句(即)中与
std::string
not withchar
数组进行比较。"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]
您正在检查
std::variant<float, int, bool, std::string>
(iev
) 与 typechar [7]
(ie type oflinear
)。当条件达到operator==
' 的定义时,您再次执行相同的操作return v == t; // checking std::variant == char [7]
这会导致对模板
operator==
本身的递归调用,从而导致堆栈溢出。
为了修复,您需要强文本以通过索引或类型显式指定变体中的值。例如,使用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;
}
或者干脆(学分@Barry)
template<typename T>
bool operator==(const std::variant<float, int, bool, std::string>& v, T const& t)
{
return std::get<T>(v) == t;
}
现在,如果您传递除 contains 以外的任何其他类型v
,您将收到 templated 的编译时错误operator==
。
通用解决方案!
对于泛型std::varaint<Types...>
,可以执行以下操作。此外,SFINAE d 仅适用于已通过的那些类型std::variant<Types>
。我已经使用了is_one_of
这篇文章的特征。
(见在线直播)
#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;
}
推荐阅读
- c# - 为什么要使用没有 setter 的 getter?
- mysql - sql查询问题从sql查询中找出表名
- python - psycopg2 无法连接到 docker 镜像
- java - 无法从 PHP Mysql 中检索图像
- python - 使用 BeautifulSoup 打印目录中所有 html 文件的内容
- javascript - 为什么javascript表现出奇怪的行为?
- django - 如何访问模板中的不同模型?
- android-studio - Android Studio Canary - 找不到代码样式选项
- jquery - 收到前响应后一一调用ajax
- python - 在 Windows 上安装 Python PIP 缺少子目录?