-1

Disclaimer: this is going to be lame.

Two questions:

  1. The part driven by curiosity: what is the exact type of a quote-marked string? Prevoiusly I thought that it's a C char[] string converted to std::string when it is needed, but some type_traits experiments revealed this:

    std::is_lvalue_reference<decltype ("string")>::value; -> true
    std::is_object<std::remove_reference<decltype ("string")>>::value; -> true
    std::is_same<decltype ("string"), std::string&>::value; -> false
    
  2. The lame part: what type of argument should a function take to be able to deal with calls like fun("str")? The reason for this question is that the following example does not compile because of the static_assert:

    template <typename T>
    void fun (const T &what)
    {
        static_assert(sizeof(T) < 0, "Something unsupported");
    }
    
    void fun (std::string str)
    {
        std::cout << "Copied" << std::endl;
    }
    
    void fun (const std::string &str)
    {
        std::cout << "Lvalue" << std::endl;
    }
    
    void fun (std::string &&str)
    {
        std::cout << "Rvalue" << std::endl;
    }
    
    int main ()
    {
        fun ("str"); //static assertion failed
        return 0;
    }
    

    More over, commenting the template out causes

    error: call of overloaded 'fun(const char [4])' is ambiguous
    candidates are: [all three options]
    

    It does not seem ambiguous to me. Why does not it construct a temporary string and pass it by rvalue-reference?

Alex
  • 1,165
  • 2
  • 9
  • 27
  • Its a pointer to a constant (read-only) null-terminated (ending with `\0`) array of `char`s. – barak manos Jul 17 '16 at 14:41
  • @barakmanos Why did the `type_traits` show that it is not a pointer, but it is an lvalue-reference to an object then? – Alex Jul 17 '16 at 14:43
  • 2
    In C++, the type of string literal `"Hello"` is `const char[6]` (an array of 6 elements of type `const char`). It's pointer-like behavior is due to the array-to-pointer standard conversion. – Igor Tandetnik Jul 17 '16 at 14:44
  • Re: ambiguous overloads. All three of your overloads would accept a temporary `std::string` object equally well - hence the ambiguity. – Igor Tandetnik Jul 17 '16 at 14:47
  • Well, okay, it's quite well-known. But why did the `type_traits` identify it as not an array and not a const object? I am quite curious about the things happening inside – Alex Jul 17 '16 at 14:49
  • About the overloads: how to eliminate this ambuguity then? I thought that temporary objects are typically passed by rvalue-refs – Alex Jul 17 '16 at 14:50
  • Duplicate: http://stackoverflow.com/questions/12517983/c-what-is-the-datatype-of-string-literal. And please post only one question at a time. – juanchopanza Jul 17 '16 at 15:00
  • @juanchopanza Not a duplicate, that's why I reopened. There is a lot more to this question than answered by that one. –  Jul 17 '16 at 15:01
  • @hvd One of the two questions asked is a duplicate. The other should have been asked separately. – juanchopanza Jul 17 '16 at 15:04
  • 1
    @Alex: An array is an object. – Cheers and hth. - Alf Jul 17 '16 at 15:06
  • @juanchopanza That would make it too broad at best, still not a duplicate. –  Jul 17 '16 at 15:07
  • @Cheersandhth.-Alf. Indeed, I missed that. But you can not have an array reference – Alex Jul 17 '16 at 15:16
  • 1
    @Alex: C++ supports array references. I'm not sure how that plays out with the type trait checkers. – Cheers and hth. - Alf Jul 17 '16 at 15:16
  • @Alex The one thing you can't have is arrays of references (arrays where each element is a reference). Did you perhaps read that at some point, and misremember it as saying you can't have references to arrays? –  Jul 17 '16 at 15:21
  • No, I did not know about the 'const char **(&)** [N]' notation and combined this with knowing that we can not have pointer references – Alex Jul 17 '16 at 15:27
  • The answer to [this question](http://stackoverflow.com/questions/10007986/c-pass-an-array-by-reference), however, makes me search some more info about **C++** arrays as they are still those C pointer-equivalent things in my mind – Alex Jul 17 '16 at 15:33
  • 1
    @Alex: You can have references to pointers. – Cheers and hth. - Alf Jul 17 '16 at 16:16
  • Uh.. Well, I definitely misremember something. Thanks! – Alex Jul 17 '16 at 17:10

2 Answers2

3

String literal "str" has type const char[4]. The most appropriate function for this argument is the template function because it does not require a conversion to std::string.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

Prevoiusly I thought that it's a C char[] string converted to std::string when it is needed

Close. It's a const char [] converted to std::string when it is needed.

The lame part: what type of argument should a function take to be able to deal with calls like fun("str")?

You can use std::string. You can use const char (&) [N]. You can use const char *. However...

The reason for this question is that the following example does not compile because of the static_assert:

...you have to give overload resolution a chance. When you have

template <typename T>
void fun (const T &what)
{
    static_assert(sizeof(T) < 0, "Something unsupported");
}

then even though string literals are implicitly convertible to std::string, you say that this function can accept string literals directly. When given the choice between a function taking a string literal after an implicit conversion, and a function taking a string literal directly, the function taking it directly will be called.

More over, commenting the template out causes

error: call of overloaded 'fun(const char [4])' is ambiguous
candidates are: [all three options]

Choose between taking by value and by reference. It would be fine to have a single non-overloaded function taking std::string by value. It would also be fine to have two overloaded functions taking std::string by const & and by && reference. But by value and by reference is too much, there is no reason to prefer one over the other then.

Community
  • 1
  • 1
  • Neat! Thanks for pointing out conversion vs priority and passing by value vs passing by reference – Alex Jul 17 '16 at 15:43