C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Proposal: Allow forward declaring typedefs

From: Tiago Freire <tmiguelf_at_[hidden]>
Date: Mon, 17 Mar 2025 14:09:48 +0000
This is desperately wanted, and I feel your pain.
I’ve tried to work on this in the past and hit exactly this problem.
This is a hard problem because of type alias names.
The symbol names of things like function parameters are based on the original names not the aliased name.
You would need to declare the original names and then replicate the aliases.
It requires more work than what you would be willing to make.

The solution is modules, we have to make that work.


From: Std-Proposals <std-proposals-bounces_at_[hidden]> On Behalf Of Robin Savonen Söderholm via Std-Proposals
Sent: Monday, March 17, 2025 2:22 PM
To: std-proposals_at_[hidden]
Cc: Robin Savonen Söderholm <robinsavonensoderholm_at_[hidden]>
Subject: Re: [std-proposals] Proposal: Allow forward declaring typedefs


You get problems with function overloading and template instantiations that way:

```c++
class foo;

template <typename T>
struct bar;

void foo_bar(bar<int> const&);

void do_something_with_fwd(foo const& f) { foo_bar(f); // Explosion! }

// But what if foo = foo_bar<int>?
```
No, the solution is to forward-declare the actual type and then have the alias next to it:

template <typename T>
class complex_type;
using simple_type = complex_type<void>;

But in case of 3PP it is probably better to ask for a forward declaration.

On Mon, Mar 17, 2025, 14:13 Donald Duck via Std-Proposals <std-proposals_at_[hidden]<mailto:std-proposals_at_[hidden]>> wrote:
Some libraries such as https://github.com/nlohmann/json have classes which are in fact typedefs for very complicated types, for example:

template<template<typename U, typename V, typename... Args> class ObjectType =
         std::map,
         template<typename U, typename... Args> class ArrayType = std::vector,
         class StringType = std::string, class BooleanType = bool,
         class NumberIntegerType = std::int64_t,
         class NumberUnsignedType = std::uint64_t,
         class NumberFloatType = double,
         template<typename U> class AllocatorType = std::allocator,
         template<typename T, typename SFINAE = void> class JSONSerializer =
         adl_serializer,
         class BinaryType = std::vector<std::uint8_t>,
         class CustomBaseClass = void>
class basic_json;
using json = basic_json<>;

I would like to forward declare their json class like this:

class json;

The problem is that if I try doing this, I get the following error:

nlohmann/json.hpp: error: conflicting declaration ‘using json = class basic_json<>’
main.cpp: note: previous declaration as ‘class json’

I don't see why this should be an error. class json; declares an incomplete type called json and I can't access its members, instantiate it, etc anyway unless I include its definition. So it shouldn't matter if it's a class, a typedef for a class, or even a typedef for a primitive.

So I suggest that class json; simply means that I'm forward declaring an incomplete type that can be anything, instead of meaning that it must be a class (as opposed to a typedef for a class). Alternatively, a new syntax such as typename json; could also work, as long as I don't need to copy the entire declaration for their complicated template.
--
Std-Proposals mailing list
Std-Proposals_at_[hidden]<mailto:Std-Proposals_at_[hidden]>
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2025-03-17 14:09:51