Date: Tue, 7 May 2024 13:10:10 +0200
If you want to introduce new type modifiers, do not expect C++26, perhaps not even C++29.
The type system is very integral to the core language, and also many templates expect to fully exhaust the type space with definitions.
You can help in that regard with automatic conversion rules. But one would not want to introduce any unexpected bugs here. And also not introduce less than optimal future behaviour for the sake of premature compatibility fixes.
The other more fundamental question is: Does one really want to distinguish between those variables of different lifetime or storage in the type system with a basic type modifier?
There are many more ways, how variables can be allocated: Different heaps, different NUMA regions, different sub-devices (e.g. GPUs), volatile/non-volatile memory.
Fundamentally changing the language with only plain old microcontrollers with ROM in mind as a technological use-case seems a bit short-sighted for a language change, one would do every 40 years or so (if at all).
-----Ursprüngliche Nachricht-----
Von:Frederick Virchanza Gotham via Std-Proposals <std-proposals_at_[hidden]>
Gesendet:Di 07.05.2024 12:32
Betreff:Re: [std-proposals] Function only accepts parameter that will persist
An:std-proposals_at_[hidden];
CC:Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>;
On Mon, May 6, 2024 at 8:44 PM Arthur O'Dwyer wrote:
>
> For example,
> constexpr int x = Func(1, 2);
> is certainly required to constant-evaluate `Func`.
> const int x = Func(1, 2);
> is at least encouraged [and in fact it is required] to attempt to constant-evaluate `Func`,
> although of course that constant-evaluation attempt might fail and then it would have
> to retry as a non-constant expression.
<snip>
> Meanwhile, the original subject of the top-level thread is about "how do I know if I've got
> a pointer to ROM/.rodata or a pointer to plain old RAM/.data (that might change)?"
<snip>
> if `f("hello")` is supposed to call `f(__rom const char*)`, then `decltype("hello")` must be
> `__rom const char[6]` instead of plain `const char[6]`... and that's going to break a lot of
> existing metaprogrammers.
<snip>
> Most of your suggestions in this area have been utterly wrong (as far as anything to do
> with WG21 is concerned) because you're conflating "const" with "static storage duration"
> and (even more importantly) with "lifetime."
You're right that I was barking up the wrong tree with relying on
'consteval' to determine if a string is static-duration const.
Let's say I start out with a struct:
struct Frog {
long i, j, k;
};
And I code a function such as:
void Func( Frog &&f );
And then I invoke this function as follows:
int main(void) { Func( Frog{1,2,3} ); }
I think that most (if not all) compilers would invoke 'Func' in this
context by passing it a pointer to a static-duration const array of 3
long's (most likely located in a page of memory marked as read-only).
However a quirky compiler could possibly code 'main' as follows:
push 3
push 2
push 1
mov rdi, rsp
call Func
add rsp, 24 // pop three long's
mov rdi, 0
jmp _Exit
In the above x86_64 assembler, I allocate space for three long's on
the stack, I set the values of the 3 long's on the stack, I put the
address of the array into the RDI register (i.e. the first parameter),
I call the function, and I restore the stack pointer. So the point I
want to make here is that a compound literal might not be of
static-duration. With that said though, I don't know if there's any
extant compiler that would do this -- maybe every extant C++ compiler
would use a static-duration const array located in a read-only page of
memory.
String literals are compound arrays however they're odd in that
they're Lvalues instead of Rvalues.
What I wanted when writing the constructor for 'efficient_string' is
that I wanted to code an optimisation as follows: "If the argument is
a static-duration string that will never change, don't copy it".
So having thought about this a little more . . . I think the easiest
and most simple way to achieve this in C++26 would be as follows:
* We have a new keyword 'static_duration_const' which is a type modifier
* All static-duration POD-compound literals (and yes all string
literals) have the 'static_duration_const' modifier
* An object with the 'static_duration_const' modifier implicitly
converts to an object without said modifier
So if we write a string literal like "Hello", then its type is:
char static_duration_const [6]
There is an implicit conversion from "char static_duration_const [6]"
to "char [6]".
So then we could write two constructors as follows:
efficient_string( char static_duration_const * )
{
// don't copy the string
}
efficient_string( char const * )
{
// copy the string
}
And then let's say I write a small program as follows:
char const *const *g_argv = nullptr;
int main(int const argc, char **const argv)
{
g_argv = argv;
efficient_string s( g_argv[0] );
}
The above snippet will copy the string -- but let's say that I want to
promise to the compiler that 'g_argv[0]' is a static-duration const
string that will never change . . . well I can use a cast to make this
promise:
efficient_string s( (char static_duration_const*)g_argv[0] );
And so now the string isn't copied.
In all of the code I've written above: Instead of having a new
keyword 'static_duration_const', maybe we could just re-use the
'constexpr' keyword here? So we'd have:
1 - The type of "Hello" is: char constexpr [6]
2 - There is an implicit conversion from "char constexpr [6]" to "char [6]".
3 - The non-copying constructor is efficient_string( char constexpr * )
4 - The copying constructor is efficient_string( char const * )
5 - The "promise cast" is efficient_string s( (char constexpr*)g_argv[0] );
How does that sound?
--
Std-Proposals mailing list
Std-Proposals_at_[hidden]
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
Received on 2024-05-07 11:10:14