Referring to a class defined inside a function scope
Asked Answered
O

1

11

In C++1y, it is possible for a function's return type to involve locally defined types:

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

The class name C is not in scope outside the body of foo, so you can create class instances but not specify their type:

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

Sometimes it is desirable to specify a type explicitly. That is, it is useful to write "the type C that is defined in foo" instead of "whatever type foo returns." Is there a way to write the type of foo's return value explicitly?

Ozell answered 13/3, 2014 at 16:24 Comment(6)
Return type deduction for functions is (hopefully) in C++14, but not C++11. (In C++11, it's supported for lambdas, but only if the body is a single return statement, so you couldn't define a local type there either).Torras
Names declared at block scope generally don't have linkage (3.5/8). This means, by definition, that entities referred to by such names cannot be named outside of that scope.Ontology
@MikeSeymour Thanks, didn't realize it wasn't part of C++11. I changed C++11 to C++1y.Ozell
You could use a typedef/alias like using foo_C = decltype(foo());.Bren
@dyp, that is "whatever type foo returns." rather than "the type C that is defined in foo". The answer to the question is no.Barbe
@JonathanWakely True, but the OP is a bit ambiguous about that, see the last sentence. I agree you cannot refer to a local name directly from an outside scope.Bren
B
5
auto x            = foo(); // Type not given explicitly
decltype(foo()) y = foo(); // Provides no more information than 'auto'

So what? Why do you care what the type's "real" name is?

As dyp said in a comment, you can use a typedef to give it a name, if that makes you feel better than auto:

 using foo_C = decltype(foo());

Sometimes it is desirable to specify a type explicitly. That is, it is useful to write "the type C that is defined in foo" instead of "whatever type foo returns." Is there a way to write the type of foo's return value explicitly?

No.

There is no name for "the function scope inside foo()" just like there is no name for these scopes:

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`
  }
}
Barbe answered 13/3, 2014 at 20:9 Comment(3)
I care about a type's "real" name because it's hard to talk about things I can't name. I would like to explain that C++-style iterator libraries, such as Thrust, do something analogous to loop fusion during type inference. An iterator's type records all of the code that will go into the loop where the iterator is used. That's hard to describe when the type can't be written out in full.Ozell
You don't need to know the "real" name to talk about it, give it another name. For example, do you need to talk about std::reverse_iterator<__gnu_cxx::__normal_iterator<std::vector<int>, int*>> or is the typedef std::vector<int>::reverse_iterator more useful?Barbe
Type aliases are useful abstractions. OTOH sometimes it matters what they're hiding. To make sense of a compile-time error involving __gnu__cxx::__normal_iterator, you need to understand where the type came from. To decide whether it's worth putting in the effort to rewrite a Thrust reduction as a CUDA kernel, you need to consider what the code looks like after templates are expanded. You can't completely understand it in terms of type aliases because type inference and template expansion use the expanded type.Ozell

© 2022 - 2024 — McMap. All rights reserved.