C++ STL type_traits问题

发布于 2024-10-09 13:26:16 字数 955 浏览 0 评论 0原文

我正在观看最新的 C9 讲座 并注意到一些有趣的事情。

在他对 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";
}

模板 void bar(T t) { foo(t, 类型名称 is_integral::type()); }

这似乎比以下要复杂得多:

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

后一种做法有什么问题吗?他的方法更好吗?为什么?

谢谢。

I was watching the latest C9 lecture and noticed something interesting..

In his introduction to type_traits, Stephan uses the following (as he says, contrived) example:

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

心是晴朗的。 2024-10-16 13:26:16

基本上,第一个选项在编译时使用有关类型“完整性”的知识,第二个选项 - 将这些知识移至运行时。

这意味着我们可以使用不可编译为非整数类型的整数类型代码。

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.

惜醉颜 2024-10-16 13:26:16

下面的例子应该可以说明其中的区别。让我们添加 struct X:

struct X
{
  X(int)
  {
  }
};

并修改一个 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";
}

然后:

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

仍会编译所有 T 类型(包括整数类型;它可能会导致警告,但会编译)。

其他等效代码:

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

通常会编译失败,因为您无法为除整型和最终浮点型以外的类型实例化 X,并且无法实例化具有运算符 int() 的用户定义类(运算符 Short() 或运算符 long() 不会)做)。

The example below should illustrate the difference. Let's add struct X:

struct X
{
  X(int)
  {
  }
};

and modify one foo as below:

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).

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).

套路撩心 2024-10-16 13:26:16

对于这样一个小而人为的例子,使用第一种方法并没有太大的优势。当你遇到更复杂的情况时,优势就会显现出来。它本质上类似于在面向对象编程中使用基于继承的多态性或 if/switch 语句。更复杂的解决方案为您提供更大的灵活性;您可以轻松添加类型,而无需修改现有代码。

如果您知道所需的所有类型(例如,您正在使用布尔值,作为示例),那么更简单的解决方案可能会更好。但是,如果您没有固定的需求(需求何时固定?),从长远来看,更复杂但更灵活的解决方案可能会更容易。

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. 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 (e.g. 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.

猫卆 2024-10-16 13:26:16

使用第一种方法,您可以使用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());
}

使用第二种方法,您必须使用 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());
}

但是如果您想实现 Dispatch() 函数不使用 if/else,同时又想使用 std::is_integral::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";
}

你的 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);
 }

Using first approach, you can implement static-dispatch without usingif/else or switch.

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,

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,

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,

 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);
 }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文