2014-03-13 28 views
11

在C++ 1Y,可能的是一个函数的返回类型涉及本地定义的类型:参照的功能范围内定义的类

auto foo(void) { 
    class C {}; 
    return C(); 
} 

类名C不在范围身体外的foo,这样你就可以创建类的实例,但是没有指定其类型:

auto x   = foo(); // Type not given explicitly 
decltype(foo()) y = foo(); // Provides no more information than 'auto' 

有时需要显式地指定一个类型。也就是说,编写“在foo中定义的类型C”而不是“foo返回的任何类型”是有用的。有没有办法明确写出foo的返回值的类型?

+0

返回类型推演(希望) C++ 14,但不是C++ 11。 (在C++ 11中,它支持lambda表达式,但只有在主体是一个'return'语句,所以你也不能在那里定义一个本地类型)。 –

+1

在块范围声明的名称通常没有链接(3.5/8)。这意味着,根据定义,这些名称所指的实体不能在该范围之外命名。 –

+0

@MikeSeymour谢谢,没有意识到它不是C++ 11的一部分。我将C++ 11更改为C++ 1y。 – Heatsink

回答

5
auto x   = foo(); // Type not given explicitly 
decltype(foo()) y = foo(); // Provides no more information than 'auto' 

还等什么?你为什么在乎这个类型的“真实”名字是什么?

作为DYP中评论说,你可以使用一个typedef给它一个名字,如果这让你感觉比auto好:

using foo_C = decltype(foo()); 

有时需要显式地指定一个类型。也就是说,编写“在foo中定义的类型C”而不是“foo返回的任何类型”是有用的。有没有办法直接写出foo返回值的类型?

没有为“内部foo()功能范围”没有名字一样,有这些范围没有名字:在功能

void bar() 
{ 
    int i=0; 
    // this scope does not have a name, cannot qualify `i` 
    { 
    int i=1; 
    // this scope does not have a name, cannot qualify either `i` 
    } 
} 
+0

我关心一个类型的“真实”名字,因为很难谈论我无法命名的东西。我想解释一下,C++风格的迭代器库(如Thrust)在类型推断过程中做了类似于循环融合的事情。一个迭代器的类型记录了所有将进入迭代器使用的循环的代码。很难描述何时不能完整地写出类型。 – Heatsink

+0

你不需要知道“真实”的名字来谈论它,给它另一个名字。例如,你是否需要谈​​论'std :: reverse_iterator <__ gnu_cxx :: _ normal_iterator ,int * >>'或者是typedef'std :: vector :: reverse_iterator'更有用? –

+0

类型别名是有用的抽象。 OTOH有时候重要的是他们隐藏的东西。要理解涉及'__gnu__cxx :: __ normal_iterator'的编译时错误,您需要了解类型来自哪里。为了决定是否值得投入重写一个CUDA内核的Thrust reduction,你需要考虑扩展模板后代码的外观。你不能完全理解它的类型别名,因为类型推断和模板扩展使用扩展类型。 – Heatsink