C++ STL type_traits问题
我正在观看最新的 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
基本上,第一个选项在编译时使用有关类型“完整性”的知识,第二个选项 - 将这些知识移至运行时。
这意味着我们可以使用不可编译为非整数类型的整数类型代码。
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.
下面的例子应该可以说明其中的区别。让我们添加 struct X:
并修改一个 foo 如下:
然后:
仍会编译所有 T 类型(包括整数类型;它可能会导致警告,但会编译)。
其他等效代码:
通常会编译失败,因为您无法为除整型和最终浮点型以外的类型实例化 X,并且无法实例化具有运算符 int() 的用户定义类(运算符 Short() 或运算符 long() 不会)做)。
The example below should illustrate the difference. Let's add struct X:
and modify one foo as below:
Then:
Will still compile for all T types (including integer types; it may cause warning but will compile).
The other equivalent code:
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).
对于这样一个小而人为的例子,使用第一种方法并没有太大的优势。当你遇到更复杂的情况时,优势就会显现出来。它本质上类似于在面向对象编程中使用基于继承的多态性或 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.
使用第一种方法,您可以不使用
if/else
或switch
实现静态调度。使用第二种方法,您必须使用
if/else
或switch
块来实现,但是如果您想实现
Dispatch()
函数不使用if/else
,同时又想使用std::is_integral::value
,那么你必须重写你的>foo()
函数,就像这样,你的
Dispatch()
函数看起来像这样,Using first approach, you can implement static-dispatch without using
if/else
orswitch
.Using second approach, you've to implement this using
if/else
orswitch
block,But if you want to implement your
Dispatch()
function without usingif/else
, and at the same time you want to usestd::is_integral<T>::value
, then you have to re-write yourfoo()
function, like this,And your
Dispatch()
function would look like,