Date: Mon, 29 Apr 2024 15:13:13 +0200
For the specific use case you propose, I would use something like
std::map<std::string_view, bool(*)(bool)>
which pretty much does what you would want it to. It takes the views and
does not copy them, but does have a full std::string interface on top of
it. It comes with the usual view caveats, you must ensure they will exist
forever - but that seems to be the basis of your question, so I think it
fits.
Would this not solve the problem with C++17?
On Mon, Apr 29, 2024 at 2:43 PM Frederick Virchanza Gotham via
Std-Proposals <std-proposals_at_[hidden]> wrote:
> 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
>
std::map<std::string_view, bool(*)(bool)>
which pretty much does what you would want it to. It takes the views and
does not copy them, but does have a full std::string interface on top of
it. It comes with the usual view caveats, you must ensure they will exist
forever - but that seems to be the basis of your question, so I think it
fits.
Would this not solve the problem with C++17?
On Mon, Apr 29, 2024 at 2:43 PM Frederick Virchanza Gotham via
Std-Proposals <std-proposals_at_[hidden]> wrote:
> 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:13:26