在阅读Wikipedia's page on decltype时,我很好奇这句话,
其[decltype]的主要用途是通用的 编程,经常在哪里 名字很难,甚至不可能 依赖于模板的类型 参数。
虽然我可以理解该语句的难度部分,但是需要命名一个无法在C ++ 03下命名的类型的示例是什么?
编辑:我的观点是,因为C ++中的所有内容都有类型声明。为什么会出现无法命名类型的情况?此外,是不是设计用于产生类型信息的特质类?特质课可以替代decltype
吗?
答案 0 :(得分:13)
您链接的维基百科页面有一个完美的例子:
int& foo(int& i);
float foo(float& f);
template <class T> auto transparent_forwarder(T& t) −> decltype(foo(t)) {
return foo(t);
}
请注意foo(int&)
返回int&
(引用类型),而foo(float&)
返回float
(非引用类型)。如果没有decltype
,则模板中不可能指定一个类型,该类型表示“函数foo
的返回类型,它接受类型t
的参数T
”。
在这个例子中,它不是一个无法表达的特定具体类型 - int&
或float
可以单独表达 - 而是更高级别的泛型类类型。
编辑:并回答你对另一个答案的评论,这个例子在C ++ 03中难以形容。你不能有一个函数模板,它将包装任何函数T1 foo(T2)
并匹配包装函数的参数和返回类型。
答案 1 :(得分:11)
C ++ 0x中有类型(在C ++ 03中,但不常见),无法明确命名,例如声明decltype(f)
后的类型auto f = [](int x) -> int {return x;};
。你需要typedef
decltype
得到一些东西才能获得一个名字。 Traits类可用于确定返回类型,但它们很混乱,并且用户需要使用traits类重载来复制它们的所有函数重载;对于诸如函数(通过指针的隐式转换)应用于给定基类的所有子类的情况,这很难正确执行。
答案 2 :(得分:1)
正如您所指出的,编译器知道存在的类型,否则它将不存在。但是,在C ++ 03中程序员并不总是容易甚至无法访问它。
N1607在结论中提到以下内容:
在C ++ 2003中,不可能 表达函数的返回类型 模板在所有情况下。此外, 涉及调用的表达式 功能模板通常很有用 复杂的类型,是 实际上不可能写 手
问题是我们如何以程序员的身份访问此类型。这并不总是一个微不足道的过程,往往是不切实际的。当你有一个你想知道结果类型的表达式时,它会变得越来越复杂。为了计算结果类型,你必须将它分成几部分。使用模板无法简化此过程(无论如何都不能评估表达式)。打破表达将是容易出错,乏味和维持的噩梦。想想这段代码:
x.g()[b.a(e)]->f();
使用C ++ 98 / TR1,名称类型依赖于模板参数通常是不可行的。 Traits为我们提供了如此多的信息,但最终decltype是解决许多问题的更清晰的解决方案。元编程时可用的很多信息都是可用的,因为诸如boost或loki等库在C ++ 98语言的暗角中隐藏了一些技巧。
当然这与你的问题无关,但我相信值得一提的是C ++ 98编译器已经有机制来了解这些类型。这正是sizeof提供的,除了它返回一个大小。 decltype重用了这些功能,并以更优雅的方式解决了这些问题。
至于另一个(学术)的例子:
struct Foo
{
struct
{
int x;
} bar;
};
template<typename T>
void
f(const T& t)
{
// C++03, How can I name the type of T::bar ?
// C++0x
// decltype(t.bar) cpy;
// Do stuff with our local cpy
}
int
main()
{
f(Foo());
}