我正在观看最新的C9 lecture并注意到一些有趣的事情......
在他对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()
);
}
这似乎比以下复杂得多:
<typename T>
后一种做法有什么问题吗?他的方式更好吗?为什么呢?
感谢。
答案 0 :(得分:14)
基本上,第一个选项在编译时使用关于类型“完整性”的知识,第二个选项 - 将此知识移动到运行时。
这意味着我们可以使用不可编译非整数类型的整数类型代码。
答案 1 :(得分:9)
以下示例应说明不同之处。让我们添加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()将不会执行)
答案 2 :(得分:1)
对于这样一个小的,人为的例子,第一种方式没有太大的优势。当您遇到更复杂的情况时,优势就来了。它基本上类似于在面向对象的编程中使用基于继承的多态或if / switch语句。更复杂的解决方案可以提供更大的灵活性您可以轻松添加类型而无需修改现有代码。
如果你知道你将需要的所有类型(例如你使用布尔值作为例子),那么更简单的解决方案可能会更好。但是,如果你没有固定的要求(什么时候需要修复?),从长远来看,更复杂但更灵活的解决方案可能会更容易。
答案 3 :(得分:0)
使用第一种方法,您可以使用if/else
或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());
}
使用第二种方法,您需要使用if/else
或switch
块实现此目的,
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<T>::value
,那么您必须重新编写{{1}功能,像这样,
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()