Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this overload resolution correct?

From: Is it safe to overload char* and std::string?

#include <string>
#include <iostream>
void foo(std::string str) {
  std::cout << "std::string\n";
}

void foo(char* str) {
  std::cout << "char*\n";
}

int main(int argc, char *argv[]) {
  foo("Hello");
}

The above code prints "char*" when compiled with g++-4.9.0 -ansi -pedantic -std=c++11.

I feel that this is incorrect, because the type of a string literal is "array of n const char", and it shouldn't be possible to initialize a non-const char* with it, so the std::string overload should be selected instead. Is gcc violating the standard here?

like image 975
Brian Bi Avatar asked Jul 09 '14 19:07

Brian Bi


People also ask

What is the overload resolution?

The process of selecting the most appropriate overloaded function or operator is called overload resolution. Suppose that f is an overloaded function name. When you call the overloaded function f() , the compiler creates a set of candidate functions.

How do I fix overload resolution failed?

To correct this error In your calling statement, make the data types of the arguments match the data types of the parameters defined for the desired overload. You might have to use the CType Function to convert one or more data types to the defined types.

What do you mean by overloading of a function?

In some programming languages, function overloading or method overloading is the ability to create multiple functions of the same name with different implementations.

What is overloading in compiler design?

The type checker designed for a language like Ada that supports polymorphic functions, the type expressions are extended to include the expressions that vary with type variables. The same operation performed on different types is called overloading and are often found in object-oriented programming.


1 Answers

First, the type of string literals: They are all constant arrays of their character type.

2.14.5 String literals [lex.string]

7 A string literal that begins with u8, such as u8"asdf", is a UTF-8 string literal and is initialized with the given characters as encoded in UTF-8.
8 Ordinary string literals and UTF-8 string literals are also referred to as narrow string literals. A narrow string literal has type “array of n const char”, where n is the size of the string as defined below, and has static storage duration (3.7).
9 A string literal that begins with u, such as u"asdf", is a char16_t string literal. A char16_t string literal has type “array of n const char16_t”, where n is the size of the string as defined below; it has static storage duration and is initialized with the given characters. A single c-char may produce more than one char16_t character in the form of surrogate pairs.
10 A string literal that begins with U, such as U"asdf", is a char32_t string literal. A char32_t string literal has type “array of n const char32_t”, where n is the size of the string as defined below; it has static storage duration and is initialized with the given characters.
11 A string literal that begins with L, such as L"asdf", is a wide string literal. A wide string literal has type “array of n const wchar_t”, where n is the size of the string as defined below; it has static storage duration and is initialized with the given characters.

Next, lets see that we only have standard array decay, so from T[#] to T*:

4.2 Array-to-pointer conversion [conv.array]

1 An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue of type “pointer to T”. The result is a pointer to the first element of the array.

And last, lets see that any conforming extension must not change the meaning of a correct program:

1.4 Implementation compliance [intro.compliance]

1 The set of diagnosable rules consists of all syntactic and semantic rules in this International Standard except for those rules containing an explicit notation that “no diagnostic is required” or which are described as resulting in “undefined behavior.”
2 Although this International Standard states only requirements on C++ implementations, those requirements are often easier to understand if they are phrased as requirements on programs, parts of programs, or execution of programs. Such requirements have the following meaning:

  • If a program contains no violations of the rules in this International Standard, a conforming implementation shall, within its resource limits, accept and correctly execute2 that program.
  • If a program contains a violation of any diagnosable rule or an occurrence of a construct described in this Standard as “conditionally-supported” when the implementation does not support that construct, a conforming implementation shall issue at least one diagnostic message.
  • If a program contains a violation of a rule for which no diagnostic is required, this International Standard places no requirement on implementations with respect to that program.

So, in summary, it's a compiler bug.

(Before C++11 (C++03) the conversion was allowed but deprecated, so it would have been correct. A diagnostic in case it happened would not have been required but provided as a quality of implementation issue.)

It's a GCC bug (bug-report not found yet), and also a clang bug (found by T.C.).

The test-case from the clang bug-report, which is much shorter:

void f(char*);
int &f(...);
int &r = f("foo");
like image 179
Deduplicator Avatar answered Oct 16 '22 12:10

Deduplicator