Description
I do not know if requests/suggestions for compiler extensions are accepted, but I would like to suggest adding Rust-style using
statements as a language extension for Clang. What I mean by that is, in the Rust programming language, the use
statement has much more versatile ergonomics than in C++. Example:
use std::collections::*;
use std::env::Args;
use std::fs::{File, FileType};
use std::io;
use std::os::{linux::{fs::MetadataExt, process::PidFd}, unix::net::Incoming, windows::{io::BorrowedSocket, ffi::EncodeWide}};
use std::{thread::*, time::Duration};
If we wanted to load the same symbols into scope in C++, the equivalent code in ISO C++ (if C++ had the same standard library structure as Rust), would be:
using namespace std::collections;
using std::env::Args;
using std::fs::File;
using std::fs::FileType;
namespace io = std::io;
using std::os::linux::fs::MetadataExt;
using std::os::linux::process::PidFd;
using std::os::unix::net::Incoming;
using std::os::windows::io::BorrowedSocket;
using std::os::windows::ffi::EncodeWide;
using namespace std::thread;
using std::time::Duration;
Evidently, it is quite annoying having to write 12 lines of using
statements (compared to just 6 lines of use
statements in Rust). (The numbers 12 and 6 are not meant to demonstrate any true relationship between the average number of using
statements between C++ and Rust - these were just chosen arbitrarily to demonstrate the ergonomics.) The syntax for loading all symbols from a namespace into scope or just loading a namespace (like writing using std::io;
) is far less ergonomic and not uniform, requiring the use of words like namespace
inside the statement rather than just using
. (Certainly the glob syntax using std::*;
is simpler than writing using namespace std;
.)
The proposed syntax in C++ (again assuming the C++ standard library was equivalent to the Rust standard library), would instead be:
using std::collections::*;
using std::env::Args;
using std::fs::{File, FileType};
using std::io;
using std::os::{linux::{fs::MetadataExt, process::PidFd}, unix::net::Incoming, windows::{io::BorrowedSocket, ffi::EncodeWide}};
using std::{thread::*, time::Duration};
So the proposal is including braces in using
statements to group multiple symbols into a single statement, as well as compounding braces within braces for loading lower-depth symbols into scope within a single statement. This also proposes including the glob-syntax to load all symbols from a namespace and the syntax for loading a namespace into scope.
(Organising our using
statements in this particular order may not necessarily be the most idiomatic or best practice, but once again this is done to illustrate something rather than act as a model of ideal programming style.)
For instance, if we were using the actual C++ standard library, we could instead write using std::chrono::*;
instead of using namespace std::chrono;
. Or, instead being able to write using std::ranges;
to do:
using std::ranges;
// We can write ranges::min() instead of std::ranges::min()
int minimum = ranges::min({33, 54, 13, 802, 7, 61});
Again, I do not know if this is an appropriate place to request/suggest compiler/language extensions, but such a feature would be greatly beneficial for improving ergonomics especially as using
statements are much more viable with the addition of modules to C++, which do not export using
statements by default unlike headers.
As for aliasing types with the using
keyword, that is fine to remain as is- while Rust also contains the word as
for aliasing, introducing this to C++ as a new keyword may not be ideal.