Date: Mon, 29 Apr 2024 15:08:27 +0200
Hi Frederick,
normally even for static (storage duration) variables a destructor is called at the end of the program. So you would have to make sure those destructors are called in the right order. This is possible by a) scope hierarchy or b) class member order or c) by ownership.
To make it simpler, one would probably limit this feature to work with variables with constant initialization (https://en.cppreference.com/w/cpp/language/constant_initialization). Those variables basically can be constructed during compile-time and stored in read-only memory.
Effectively you introduce constexpr parameter types as suggested by
- P1045 constexpr Function Parameters by David Stone (https://github.com/cplusplus/papers/issues/603)
- P2781 std::constexpr_wrapper by Matthias Kretz & Zach Laine (https://github.com/cplusplus/papers/issues/1458)
To make it more complete, one would change the language to better statically follow and guarantee lifetime dependencies even beyond the aforementioned a) to c).
This is related to lifetime safety enhancements of C++.
Best,
Sebastian
-----Ursprüngliche Nachricht-----
Von:Frederick Virchanza Gotham via Std-Proposals <std-proposals_at_[hidden]>
Gesendet:Mo 29.04.2024 14:43
Betreff:[std-proposals] Function only accepts parameter that will persist
An:std-proposals <std-proposals_at_[hidden]>;
CC:Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>;
Last week I was programming a microcontroller that had run out of heap
memory. There was a global 'std::map' object which mapped the name of
a command (e.g. "VERSION") to the address of the function that handled
that command, as follows:
std::map< String, bool(*)(bool) > g_command_map;
I looked through the code to see where commands were being added to
the map, and I saw that every single one of them was a static-duration
constant string, using "operator[]" as follows:
g_command_map["VERSION"] = &CommandHandler_Version;
Therefore the copying of the string into a heap-allocated 'String'
object was unnecessary. So I was able to write my own 'Map' class that
just stored a pointer to a null-terminated string, and I wrote
'Map::operator[]' to use 'std::strcmp' to check for equality.
Of course though, my new map class would malfunction if you gave it either:
(1) A pointer to a static-duration string which would later change
(2) A pointer to a stack string
(3) A pointer to a heap string which would later change
(4) A pointer to a heap string which would later be deallocated
Has anyone ever explored the idea of having a way of defining a
function which receives a pointer to an object which is guaranteed to
exist forever? So instead of having:
void MyMapClass::operator[](char const *);
We might have something like:
void MyMapClass::operator[](static char const *);
And so if you were to try to invoke the latter as follows:
int main(void)
{
char str[] = "donkey";
str[0] = 'm';
mymap[str] = 123;
str[0] = 'z';
}
then you would get a compiler error because the object referred by the
decayed 'str' is not of static duration. Similarly the following would
give a compiler error:
int main(void)
{
char *const str = new char[16u];
strcpy(str, "monkey");
mymap[str] = 123;
}
In order to get the above snippet to compile, you would need to
express your guarantee to the compiler that the object referred by
'str' will exist forever, perhaps by just writing 'static' before the
argument:
int main(void)
{
char *const str = new char[16u];
strcpy(str, "monkey");
mymap[ static str ] = 123;
}
We would of course though need to consider the possibility of bugs
being introduced by programmers mis-using the 'static' keyword in this
context -- for example let's say you were to guarantee the immortality
of an object and then later deallocate it before the program ends.
Next we would have to discuss what effect 'const' has in the following
function signature:
void MyMapClass::operator[](static char const *);
Does the 'const' mean that the function won't modify the string, or
does it mean that the string is guaranteed not to be changed elsewhere
for the remainder of the program? Well, here we could use 'const' with
'mutable' as follows:
void MyMapClass::operator[](static char*) - Function cannot alter
object, but other functions can
void MyMapClass::operator[](static char const*) - Function cannot
alter object, nor can other functions
void MyMapClass::operator[](static char mutable*) - Function can
alter object, and so can other functions
void MyMapClass::operator[](static char mutable const*) - Function
can alter object, but other functions cannot
We could also allow overloading, so that we could have two functions as follows:
void MyMapClass::operator[](static char const *const p, int const x)
{
// No need to copy the string in here
}
void MyMapClass::operator[](char const *const p, int const x)
{
// We must copy the string in here
char *const q = new char[strlen(p) + 1u];
std::strcpy(q,p);
(*this)[static q] = x; // Invoke the above function
}
And we'd have to discuss how long "forever" lasts? Does it mean to the
end of the program? Or does it just mean until right before all of the
"atexit" registered functions are called?
Of course this is just a half-baked idea that I wish to float on the
mailing list to see if anyone can see any merit in it.
--
Std-Proposals mailing list
Std-Proposals_at_[hidden]
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
Received on 2024-04-29 13:08:30