简体   繁体   English

C ++ STL type_traits问题

[英]C++ STL type_traits question

I was watching the latest C9 lecture and noticed something interesting.. 我正在观看最新的C9讲座并注意到一些有趣的东西......

In his introduction to type_traits, Stephan uses the following (as he says, contrived) example: 在他对type_traits的介绍中,Stephan使用了以下(正如他所说的,做作的)示例:

template <typename T> void foo(T t, true_type)
{
    std::cout << t << " is integral";
}
template <typename T> void foo(T t, false_type)
{
    std::cout << t << " is not integral";
}

template <typename T> void bar(T t) { foo(t, typename is_integral<T>::type()); }

This seems to be far more complicated than: 这看起来要复杂得多:

template <typename T> void foo(T t)
{
    if(std::is_integral<T>::value)
        std::cout << "integral";
    else
        std::cout << "not integral";
}

Is there something wrong with the latter way of doing it? 这样做的方法有问题吗? Is his way better? 他的方式更好吗? Why? 为什么?

Thanks. 谢谢。

Basically first option uses knowledge about "integrality" of the type at compile-time and the second option - moves this knowledge to run-time. 基本上,第一个选项在编译时使用关于类型的“完整性”的知识,第二个选项 - 将此知识移动到运行时。

This means that we may use for integral types code which is not compilable for non-integral types. 这意味着我们可以使用不可编译为非整数类型的整数类型代码。

The example below should illustrate the difference. 下面的例子应该说明不同之处。 Let's add struct X: 让我们添加struct X:

struct X
{
  X(int)
  {
  }
};

and modify one foo as below: 并修改一个foo如下:

template <typename T> void foo(T t, true_type)
{
    std::cout << t << " is integral";
    X x(t);
}
template <typename T> void foo(T t, false_type)
{
    std::cout << t << " is not integral";
}

Then: 然后:

template <typename T> void bar(T t)
{
    foo(t, typename is_integral<T>::type());
}

Will still compile for all T types (including integer types; it may cause warning but will compile). 仍然会为所有T类型编译(包括整数类型;它可能会导致警告,但会编译)。

The other equivalent code: 其他等效代码:

template <typename T> void foo(T t)
{
    if(std::is_integral<T>::value)
    {
        std::cout << "integral";
        X x(t);
    }
    else
        std::cout << "not integral";
}

will often fail to compile as you will not be able to instantiate X for types other then integral and eventually floating point and user defined classes which have operator int() (operator short() or operator long() will not do). 通常会无法编译,因为您将无法为其他类型实例化X,而最终浮点和用户定义的类具有运算符int()(运算符short()或运算符long()将不会)。

For such a small, contrived example, there is not much advantage to doing it the first way. 对于这样一个小的,人为的例子,第一种方式没有太大的优势。 The advantage comes when you have more complex situations. 当您遇到更复杂的情况时,优势就来了。 It's essentially analogous to using inheritance-based polymorphism or if/switch statements in object-oriented programming. 它基本上类似于在面向对象的编程中使用基于继承的多态或if / switch语句。 The more complex solution allows you greater flexibility; 更复杂的解决方案可以提供更大的灵活性 you can easily add types without modifying existing code. 您可以轻松添加类型而无需修改现有代码。

If you know all of the types you will ever need (eg you are using a boolean, as the example), then the simpler solution may be better. 如果你知道你将需要的所有类型(例如你使用布尔值作为例子),那么更简单的解决方案可能会更好。 But if you do not have fixed requirements (and when are requirements ever fixed?), the more complex, but more flexible solution will probably be easier in the long run. 但是如果你没有固定的要求(什么时候需要修复?),从长远来看,更复杂但更灵活的解决方案可能会更容易。

Using first approach, you can implement static-dispatch without using if/else or switch . 使用第一种方法,您可以在使用if/elseswitch 情况下实现静态分派。

template <typename T> 
void Dispatch(T t)
{
    //Call foo(T, true_type) or foo(T, false_type)
    //depending upon the *type* of second parameter.
    foo(t, typename is_integral<T>::type());
}

Using second approach, you've to implement this using if/else or switch block, 使用第二种方法,你要使用if/elseswitch块来实现它,

template <typename T> 
void Dispatch(T t)
{
    //Call foo(T, true_type) or foo(T, false_type)
    //depending upon the *value* of value.
    if(std::is_integral<T>::value)
        foo(t, true_type());
    else
        foo(t, false_type());
}

But if you want to implement your Dispatch() function without using if/else , and at the same time you want to use std::is_integral<T>::value , then you have to re-write your foo() function, like this, 但是如果你想在不使用if/else情况下实现你的Dispatch()函数,并且同时你想使用std::is_integral<T>::value ,那么你必须重新编写你的foo()函数,像这样,

template <bool b> 
void foo(T t)
{
    std::cout << t << " is integral";
}

template <> 
void foo<false>(T t)
{
    std::cout << t << " is not integral";
}

And your Dispatch() function would look like, 你的Dispatch()函数看起来像,

 template <typename T> 
 void Dispatch(T t)
 {
     //using std::is_integral<T>::value!
     const bool selector = (bool) std::is_integral<T>::value;
     foo<selector>(t);
 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM