- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我在代码中大量使用变体,我需要在某些地方与内容进行比较,以测试变体内容的值(value)。
例如:
if(equals<int>(aVariant, 0)){
//Something
} else {
//Something else
}
我为此目的编写了这个简单的模板函数:
template<typename V, typename T>
inline bool equals(V& variant, T value){
return boost::get<T>(&variant) && boost::get<T>(variant) == value;
}
这很好用,但代码开始难以阅读。我更喜欢这样使用比较运算符:
if(aVariant == 0){
//Something
} else {
//Something else
}
但我无法提供有效的运算符实现。问题是 == 运算符已经在编译时失败的变体中实现......
有人知道实现它的方法吗?或者禁用此限制的方法?即使我必须为变体中包含的每种可能类型实现一个版本,这也不是问题。
谢谢
最佳答案
如评论所述,我认为解决此难题的最简洁方法是加强 boost::variant<>
的实现具有允许客户端覆盖行为以供外部使用的运营商策略(实际上是每个运营商)。 (显然这是大量的通用编程工作)。
我已经实现一个解决方法。这使您可以为变体 实现自定义运算符,即使它已经在 boost/variant.hpp
中实现了这些运算符。 .
我的想法是使用 BOOST_STRONG_TYPEDEF
.
我们的想法是通过使我们的变体具有不同的实际类型来打破重载解决方案(或者至少使我们的自定义重载成为首选解决方案)(这有点让人想起“绝望的”ADL 障碍: 你不能 un- using
范围内的可见名称,并且你不能转到“非军事化命名空间”(屏障),因为冲突声明位于类命名空间本身;但您可以让它们不应用于您的“诱饵”类型)。
唉,这对 operator<
不太适用和家族,因为 boost strong-typedef 实际上非常努力地使用“基本”类型来保留(弱)总排序语义。在普通英语中:strong typedefs define operator<
还有(委派给基类型的实现)。
别担心,我们可以做一个 CUSTOM_STRONG_TYPEDEF 并继续我们的快乐之路。查看 main 中的测试用例以获得概念证明(下面的输出)。
由于描述了有趣的交互,我选择了 operator<
对于这个演示,但我想你不会有任何方式获得自定义 operator==
寻找您的变体类型。
#include <boost/variant.hpp>
#include <boost/lexical_cast.hpp>
#include <string>
#include <iostream>
/////////////////////////////////////////////////////
// copied and reduced from boost/strong_typedef.hpp
#define CUSTOM_STRONG_TYPEDEF(T, D) \
struct D \
/*: boost::totally_ordered1< D */ \
/*, boost::totally_ordered2< D, T */ \
/*> > */ \
{ \
T t; \
explicit D(const T t_) : t(t_) {}; \
D(){}; \
D(const D & t_) : t(t_.t){} \
D & operator=(const D & rhs) { t = rhs.t; return *this;} \
D & operator=(const T & rhs) { t = rhs; return *this;} \
operator const T & () const {return t; } \
operator T & () { return t; } \
/*bool operator==(const D & rhs) const { return t == rhs.t; } */\
/*bool operator<(const D & rhs) const { return t < rhs.t; } */\
};
namespace detail
{
typedef boost::variant<unsigned int, std::string> variant_t;
struct less_visitor : boost::static_visitor<bool>
{
bool operator()(const std::string& a, int b) const
{ return boost::lexical_cast<int>(a) < b; }
bool operator()(int a, const std::string& b) const
{ return a < boost::lexical_cast<int>(b); }
template <typename T>
bool operator()(const T& a, const T& b) const
{ return a < b; }
};
struct variant_less
{
less_visitor _helper;
bool operator()(const variant_t& a, const variant_t& b) const
{ return boost::apply_visitor(_helper, a, b); }
};
}
CUSTOM_STRONG_TYPEDEF(detail::variant_t, custom_vt);
namespace
{
bool operator<(const custom_vt& a, const custom_vt& b)
{ return detail::variant_less()(a, b); }
std::ostream& operator<<(std::ostream& os, const custom_vt& v)
{ return os << (const detail::variant_t&)v; }
}
int main()
{
const detail::variant_t I(43), S("42");
const custom_vt i(I), s(S);
// regression test (compare to boost behaviour)
std::cout << "boost: " << I << " < " << S << ": " << std::boolalpha << (I<S) << "\n";
std::cout << "boost: " << S << " < " << I << ": " << std::boolalpha << (S<I) << "\n";
// FIX1: clumsy syntax (works for boost native variants)
detail::variant_less pred;
std::cout << "clumsy: " << i << " < " << s << ": " << std::boolalpha << pred(i,s) << "\n";
std::cout << "clumsy: " << s << " < " << i << ": " << std::boolalpha << pred(s,i) << "\n";
std::cout << "clumsy: " << I << " < " << S << ": " << std::boolalpha << pred(I,S) << "\n";
std::cout << "clumsy: " << S << " < " << I << ": " << std::boolalpha << pred(S,I) << "\n";
// FIX2: neat syntax (requires a custom type wrapper)
std::cout << "custom: " << i << " < " << s << ": " << std::boolalpha << (i<s) << "\n";
std::cout << "custom: " << s << " < " << i << ": " << std::boolalpha << (s<i) << "\n";
}
输出:
boost: 43 < 42: true
boost: 42 < 43: false
clumsy: 43 < 42: false
clumsy: 42 < 43: true
clumsy: 43 < 42: false
clumsy: 42 < 43: true
custom: 43 < 42: false
custom: 42 < 43: true
当然,如果您想将 custom_vt 传递到使用 TMP 对变体进行操作的库 API,则可能会出现不幸的交互。然而,由于两者之间的无痛转换,您应该能够在适当的时候使用 detail::variant_t 来“杀出一条血路”。
这是您为在调用站点获得句法便利而必须付出的代价。
关于c++ - 如何在包含类型的变体上使用比较运算符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9153227/
我正在尝试编写一个相当多态的库。我遇到了一种更容易表现出来却很难说出来的情况。它看起来有点像这样: {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE
谁能解释一下这个表达式是如何工作的? type = type || 'any'; 这是否意味着如果类型未定义则使用“任意”? 最佳答案 如果 type 为“falsy”(即 false,或 undef
我有一个界面,在IAnimal.fs中, namespace Kingdom type IAnimal = abstract member Eat : Food -> unit 以及另一个成功
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: What is the difference between (type)value and type(va
在 C# 中,default(Nullable) 之间有区别吗? (或 default(long?) )和 default(long) ? Long只是一个例子,它可以是任何其他struct类型。 最
假设我有一个案例类: case class Foo(num: Int, str: String, bool: Boolean) 现在我还有一个简单的包装器: sealed trait Wrapper[
这个问题在这里已经有了答案: Create C# delegate type with ref parameter at runtime (1 个回答) 关闭 2 年前。 为了即时创建委托(dele
我正在尝试获取图像的 dct。一开始我遇到了错误 The function/feature is not implemented (Odd-size DCT's are not implemented
我正在尝试使用 AFNetworking 的 AFPropertyListRequestOperation,但是当我尝试下载它时,出现错误 预期的内容类型{( “应用程序/x-plist” )}, 得
我在下面收到错误。我知道这段代码的意思,但我不知道界面应该是什么样子: Element implicitly has an 'any' type because index expression is
我尝试将 SignalType 从 ReactiveCocoa 扩展为自定义 ErrorType,代码如下所示 enum MyError: ErrorType { // .. cases }
我无法在任何其他问题中找到答案。假设我有一个抽象父类(super class) Abstract0,它有两个子类 Concrete1 和 Concrete1。我希望能够在 Abstract0 中定义类
我想知道为什么这个索引没有用在 RANGE 类型中,而是用在 INDEX 中: 索引: CREATE INDEX myindex ON orders(order_date); 查询: EXPLAIN
我正在使用 RxJava,现在我尝试通过提供 lambda 来订阅可观察对象: observableProvider.stringForKey(CURRENT_DELETED_ID) .sub
我已经尝试了几乎所有解决问题的方法,其中包括。为 提供类型使用app.use(express.static('public'))还有更多,但我似乎无法为此找到解决方案。 index.js : imp
以下哪个 CSS 选择器更快? input[type="submit"] { /* styles */ } 或 [type="submit"] { /* styles */ } 只是好
我不知道这个设置有什么问题,我在 IDEA 中获得了所有注释(@Controller、@Repository、@Service),它在行号左侧显示 bean,然后转到该 bean。 这是错误: 14-
我听从了建议 registering java function as a callback in C function并且可以使用“简单”类型(例如整数和字符串)进行回调,例如: jstring j
有一些 java 类,加载到 Oracle 数据库(版本 11g)和 pl/sql 函数包装器: create or replace function getDataFromJava( in_uLis
我已经从 David Walsh 的 css 动画回调中获取代码并将其修改为 TypeScript。但是,我收到一个错误,我不知道为什么: interface IBrowserPrefix { [
我是一名优秀的程序员,十分优秀!