动机:我想创建一个实用程序类,而不必写:
if( someVal == val1 || someVal == val2 || someVal == val3 )
我可以写一下:
if( is(someVal).in(val1, val2, val3) )
更接近于数学'a是(b,c,d)'的元素,并且当变量名'someVal'很长时也会节省大量的输入。
这是我到目前为止的代码(对于2和3个值):
template<class T>
class is {
private:
T t_;
public:
is(T t) : t_(t) { }
bool in(const T& v1, const T& v2) {
return t_ == v1 || t_ == v2;
}
bool in(const T& v1, const T& v2, const T& v3) {
return t_ == v1 || t_ == v2 || t_ == v3;
}
};
但是如果我写的话,它就无法编译:
is(1).in(3,4,5);
相反,我必须写
is<int>(1).in(3,4,5);
这不是太糟糕,但如果编译器能够以某种方式判断出类型为int
并且我必须明确指定它,那会更好。
无论如何要做到这一点,或者我坚持明确指定它?
答案 0 :(得分:14)
如果要保留此语法,可以使用辅助函数,如:
template<class T>
class is_op {
private:
T t_;
public:
is_op(T t) : t_(t) { }
bool in(const T& v1, const T& v2) {
return t_ == v1 || t_ == v2;
}
bool in(const T& v1, const T& v2, const T& v3) {
return t_ == v1 || t_ == v2 || t_ == v3;
}
};
template< class U >
inline is_op<U> is( U const& v )
{
return is_op<U>( v );
}
int main(int argc, char* argv[])
{
is( 1 ).in( 1 , 2 , 4 );
}
答案 1 :(得分:5)
这个问题非常有趣,布尔条件可能会变得很毛茸茸。
我自己倾向于更喜欢写特殊功能,因为这里的含义很难传达。做什么:
if (someVal == val1 || someVal == val2 || someVal == val3)
意味着什么?
是
if ( is(someval).in(val1, val2, val3) )
// or
if ( is(someval).in(val1)(val2)(val3) ) // implements short-circuiting
// and removes arity issue
// using a proxy object
更好?
我认为用以下内容阅读会更容易:
bool isToBeLogged(const Foo& foo)
{
// Either
static std::set<Foo> ValuesToLog = /* some boost assign magic or whatever */;
return ValuesToLog.find(foo) != ValuesToLog.end();
// Or
return foo == val1 || foo == val2 || foo == val3;
}
if (isToBeLogged(someVal))
我想这是一种风格问题。
第二种方法的优点包括:
不健康?我想这更像打字......哦,好吧:p
答案 2 :(得分:1)
template<typename T>
is<T> is_value(T value)
{
return is<T>(value);
}
int main()
{
bool r ;
r = is_value(1).in(3,4,5);
r = is_value(3).in(3,4,5);
return 0;
}
答案 3 :(得分:1)
关于一般问题,像contains这样的实用函数可能很方便:
#include <boost/range.hpp>
template <class Range, class T>
bool contains(const Range& range, const T& value)
{
return std::find(boost::begin(range), boost::end(range), value) != boost::end(range);
}
(Boost的使用使得它也接受数组,尽管可能会单独编写该重载。对于具有find成员函数的容器,这也可能会重载。)
在C ++ 0x中,这可以扩展为支持std::initializer_list<T>
*允许相当不错的用法:
if (contains({1, 2, 3}, value) {...}
*不确定它是否应该不起作用,但我的编译器需要重载才能使其正常工作。
答案 4 :(得分:0)
你坚持使用它 - 构造函数需要提供类型作为模板参数。我应该观察到我真的不喜欢你的想法(尤其是班级名称)。为什么不使用std :; set?甚至是模板功能 - 类似于:
template <typename T>
bool IsIn( T v, T a, T b, T c ) {
...
}
答案 5 :(得分:0)
对比较类的修改可能是使用varargs,使其对该集合的n个元素具有通用性。