Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;模板类型演绎问题_C++_Templates - Fatal编程技术网

C++ C++;模板类型演绎问题

C++ C++;模板类型演绎问题,c++,templates,C++,Templates,动机:我想创建一个实用程序类,这样就不必编写: if( someVal == val1 || someVal == val2 || someVal == val3 ) 我可以写: if( is(someVal).in(val1, val2, val3) ) 这与数学上的“a是(b,c,d)的一个元素”更为接近,而且当变量名“someVal”很长时,还可以节省大量的键入时间 以下是我到目前为止的代码(针对2和3个值): 相反,我必须写作 is<int>(1).in(3,4,5);

动机:我想创建一个实用程序类,这样就不必编写:

if( someVal ==  val1 || someVal == val2 || someVal == val3 )
我可以写:

if( is(someVal).in(val1, val2, val3) )
这与数学上的“a是(b,c,d)的一个元素”更为接近,而且当变量名“someVal”很长时,还可以节省大量的键入时间

以下是我到目前为止的代码(针对2和3个值):

相反,我必须写作

is<int>(1).in(3,4,5);
is(1).in(3,4,5);
这还不算太糟,但如果编译器能够在不需要我显式指定的情况下找出类型是
int
,那就更好了。

是否仍要这样做,或者我必须明确指定它?

您必须这样做-构造函数要求将类型作为模板参数提供。我应该注意到我真的不喜欢你的想法(尤其是类名)。为什么不使用std:;设置或者甚至是模板函数-类似于:

template <typename  T>
bool IsIn( T v, T a, T b, T c ) {
   ...
}
模板
布尔IsIn(tV、tA、tB、tC){
...
}

如果要保留此语法,可以使用以下帮助函数:

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 );
}
模板
上课时间很长{
私人:
T!;
公众:
is_op(T T):T_(T){}
bool-in(常数T&v1,常数T&v2){
返回t_==v1 | t_==v2;
}
bool-in(常数T&v1、常数T&v2、常数T&v3){
返回t|u==v1 | t|u==v2 | t|u==v3;
}
};
模板
内联is_op is(U const&v)
{
返回值为_op(v);
}
int main(int argc,char*argv[])
{
is(1)、in(1,2,4);
}
模板
is_值(T值)
{
返回值为(值);
}
int main()
{
布尔r;
r=是_值(1)。in(3,4,5);
r=是_值(3)。in(3,4,5);
返回0;
}

这个问题很有趣,布尔条件确实会变得复杂

我自己倾向于编写特殊函数,因为这里的意思很难表达。什么是:

if (someVal == val1 || someVal == val2 || someVal == val3)
意味着什么

更好

我认为用以下方法阅读会更容易:

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))
bool-istobeloged(const-Foo&Foo)
{
//或者
static std::set ValuesToLog=/*一些boost赋值魔术或其他什么*;
返回ValuesToLog.find(foo)!=ValuesToLog.end();
//或
返回foo==val1 | | foo==val2 | | foo==val3;
}
如果(istobelogd(someVal))
我想这是风格的问题

第二种方法的优点包括:

  • 如果测试不止一次,那么逻辑不会分散(因此更改很容易)
  • 不需要对测试进行注释,方法名已经对测试进行了注释

犯人?我想更多的是打字。。。哦:p对比较类的修改可能是使用varargs,使其通用于集合的n个元素。

关于一般问题,像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);
}


*不确定它是否应该已经工作,但我的编译器需要重载才能工作。

典型方式,编写提供功能的类,然后编写一个函数来创建该类的实例,因为函数支持类型推断。实际上,我从类似于IsIn的东西开始,因为一个名为“in”的类似乎是在自找麻烦,但最后我决定为了可读性,我更喜欢(a)in(b,c)。重复使用std::set-我的用例是我希望能够在一行中完成这项工作,而不必向集合中添加成员,然后检查成员资格。(顺便说一句,我没有投你反对票)关于类名:把它放在一个名称空间中就可以了?(C++有多可能得到一个IS关键字?!这不是每个人都称之为ISTRAM的吗?)我不知道你是如何实现短路的?您不会传递函数调用的结果,而是传递在查找时调用函数的对象但是一般来说,您不能将这些方法结合起来(使用is.in实现iStobelogd)吗?varargs不适用于大多数类型的t?C++0x中的可变模板或初始值设定项列表将是另一回事。
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))
#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);
}
if (contains({1, 2, 3}, value) {...}