• Overloading function for string literal with size

    From Marcel Mueller@21:1/5 to All on Fri May 17 17:25:24 2024
    Assuming I have a function

    void assign(const char* str);
    void assign(const char* str, size_t len);

    If this is called with a string literal, always the string length has to
    be examined at runtime.

    With

    template<size_t N>
    void assign(const char (&str)[N]);

    I can capture the string length (including \0) at compile time.
    But this overload is never used because the first overload still fits to
    the literal due to the implicit conversion from array to pointer.

    How to force the last overload with fixed size char arrays?


    Marcel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paavo Helde@21:1/5 to Bonita Montero on Fri May 17 20:56:40 2024
    On 17.05.2024 19:56, Bonita Montero wrote:

    void svFn( string_view const &sv )

    In general, string_view should be passed by value, not by reference, as
    it is small enough. When I started to use string_view I did some
    research and figured out pass-by-value is more appropriate.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Marcel Mueller@21:1/5 to All on Sat May 18 08:01:01 2024
    Am 17.05.24 um 17:45 schrieb Bonita Montero:
    Take a string_view as an argument. With a char-literal
    counting the characters is constexpr'd at compile-time.

    I should have mentioned C++11, sorry.

    But I am in doubt that this would help.
    When an overload with const char* exists why should the compiler prefer
    a string_view as proxy class?


    Marcel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Markus Schaaf@21:1/5 to All on Tue May 21 13:54:20 2024
    Am 17.05.24 um 17:25 schrieb Marcel Mueller:
    Assuming I have a function

    void assign(const char* str);
    void assign(const char* str, size_t len);

    As another suggestion: If you like your interfaces lean and
    clean, then the second overload is the only one really needed.
    And if you prefer a more C-ish style, using plain pointer and
    separate length (instead of something like string_view), then
    C-ish convenience solutions are a good fit:

    #define STR_LIT( s ) s, (sizeof s - 1)
    assign( STR_LIT( "bla" ))

    BR

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Markus Schaaf@21:1/5 to All on Tue May 21 13:20:21 2024
    Am 17.05.24 um 17:25 schrieb Marcel Mueller:
    Assuming I have a function

    void assign(const char* str);
    void assign(const char* str, size_t len);

    If this is called with a string literal, always the string length has to
    be examined at runtime.

    With

    template<size_t N>
    void assign(const char (&str)[N]);

    I can capture the string length (including \0) at compile time.
    But this overload is never used because the first overload still fits to
    the literal due to the implicit conversion from array to pointer.

    How to force the last overload with fixed size char arrays?

    As far as I know, it is impossible. If you think about it, you
    may not want such an overload anyway. Use string_view or a custom
    class like it, and avoid plain (char const *). I have used a
    special class for string literals for a long time, before
    string_view and constexpr were invented.

    MfG

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Marcel Mueller@21:1/5 to All on Wed May 22 09:33:11 2024
    Am 21.05.24 um 13:20 schrieb Markus Schaaf:
    Am 17.05.24 um 17:25 schrieb Marcel Mueller:
    How to force the last overload with fixed size char arrays?

    As far as I know, it is impossible. If you think about it, you may not
    want such an overload anyway. Use string_view or a custom class like it,
    and avoid plain (char const *).

    In fact I have done this now - see my answer to Bonita.

    There is only one drawback. The additional conversion prevents some
    other assignments that itself used some kind of conversion like
    (operator const char*).


    From my point of view the decay from an array to a pointer type is pure
    pain that should never had made it into C++. But changing this would
    break zillions of existing code. :-(

    Maybe a function parameter should be declarable as "explicit" to forbid
    such decay:
    type& operator=(explicit const char* str);
    int foo(int x, explicit int y); // does not bind long to y

    Just an idea.

    Something similar has been introduced with the option to explicitly
    delete some unwanted overloads. But this does not cover this use case
    because the decay to a pointer takes precedence over template overloads.


    Marcel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Marcel Mueller@21:1/5 to All on Wed May 22 09:17:42 2024
    Am 19.05.24 um 15:24 schrieb Bonita Montero:
    Am 18.05.2024 um 08:01 schrieb Marcel Mueller:
    But I am in doubt that this would help.
    When an overload with const char* exists why should the compiler
    prefer a string_view as proxy class?

    I think with a string_view a char-poiner isn't necessary.
    Otherwise the overload without conversion would be preferred.

    I wonder how string_view manages to omit the call to strlen.
    There seem to be some magic which also removes the trailing 0 that all
    string literals have.

    However, although I cannot use string_view because I could at most
    upgrade to C++14 this got me into the right direction.
    Introducing a proxy class reduces the overload resolution priority:

    struct cstring
    { const char* Str;
    cstring(const char* str) : Str(str) {}
    };

    Now overloads with cstring and const char (&)[N] may coexist and the
    latter is preferred for string literals. :-)


    Marcel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Marcel Mueller@21:1/5 to All on Wed May 22 12:59:09 2024
    Am 22.05.24 um 11:55 schrieb Bonita Montero:
    I wish there could be functional default-arguments that take one
    of the primary function's parameters. Sth. like this would be nice:

    auto count = []( char const *str ) -> size_t
    {
        char const *begin = str;
        for( ; *str; ++str );
        return str - begin;
    };

    void fn( char const *str, size_t n = count( str ) );

    But referencing a parameter inside a default-argument isn't possible.

    This is normally a job for function overloading.
    The benefit is that no longer every caller needs to implement the code.


    Marcel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Marcel Mueller@21:1/5 to All on Sat May 25 07:14:48 2024
    Am 24.05.24 um 15:26 schrieb Alf P. Steinbach:
    On 2024-05-17 5:25 PM, Marcel Mueller wrote:
    How to force the last overload with fixed size char arrays?

    Three possibilities, if compile time O(1) size is what you're after:

    * string_view, if C++17 and OK to ditch the zero-termination guarantee.
    * Reducing the overload priority, as you point out in-thread.
    * Just template it.

    A hopefully C++11-compatible example of "just template it":

    Interesting approach. You basically telling me that the partial
    specialization rules differ and prefer the array implementation in doubt.


    Marcel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)