I wouldn’t give up so easily; the same issue Daveed raises (with auto-deduced return types) applies for references, but we have explicitly defined the semantics for to allow the user to distinguish:
```
int &f() {…}
auto j = f(); //j is an int
auto &jref = f(); //jref is an int&
```
The same rules could conceivably be applied by simply substituting ^ for &:
```
class A {};
consteval class^ getA() { return [:^A:]; } //returns a "reference to a class"
consteval auto^ getA2() { return getA(); } //okay
consteval auto error() { return getA(); } //error
class Foo : public getA2() {};
```
The analogy between reflection/splicing and pointers/dereferencing is extremely strong, such that the possibility of a "reference"-analog which handles the dereferencing automatically is still possible (assuming expressions can be parsed in arbitrary contexts, which I agree would seem to be possible.)
The only real possible downside is readability, which is important.
*But* let’s set the reference issue aside. This whole matter raises the much more important question: just why *aren’t* reflections strongly-typed? Why only meta::info? Why is the user not allowed to specify further type information? (Note this is *not* the same as whether to use object-oriented reflection — discussed in P1240 pp5-6, totally different issue, those arguments do not apply here.)
By adopting a universal meta::info, we are knee-capping the compiler, so that it cannot perform basic type checking on templates prior to instantiation:
That seems like a big issue. Among other things, that type checking has to be done upon each instantiation probably affects efficiency, which is the whole reason for `meta::info` in the first place.
I think adopting syntax analogous to pointers (and, arguably, references) should be considered. First step along these lines: change `meta::info` to `[:auto:]`, which is in turn analogous to `auto *` : we know it’s a reflection/pointer, but we won’t say any more about what kind of thing it reflects/points to. Same semantics as meta::info has currently.
But this leaves us space to support, now or in the future, more specific "pointer-like" reflection types: [:class:], [:template<typename>:], [:meta::expr<int>:] (reflection of an integer-typed expression), etc.
And this would in turn leave us the possibility of supporting "reference-like" analogs of those: class^, template<typename>^, meta::expr<int>^, should we wanted to allow users to do without splicing/reflecting, by instead allowing consteval expressions in arbitrary contexts, which as Rene notes seems possible.
I suppose this needs a paper. If anyone else has thoughts or has done work along these lines, please weigh in.