2017-01-03 1 views
7
#include <iostream> 
using namespace std; 

void f(const char* arg) 
{ 
    cout << "arg is a pointer" << endl; 
} 

template<size_t N> 
void f(const char (&arg)[N]) 
{ 
    cout << "arg is an array." << endl; 
} 

int main() 
{ 
    f(""); 
} 

Mon compilateur est clang 3.8.Pourquoi clang prend-il un littéral de chaîne comme un pointeur plutôt qu'un tableau?

La sortie est la suivante:

arg est un pointeur

Toutefois, selon cppreference.com,

Le type d'un est const char littéral chaîne sans préfixe [] .

Pourquoi la résolution de surcharge ne se comporte-t-elle pas comme prévu?

+2

Exemple équivalent, mais abstraction du modèle: http://melpon.org/wandbox/permlink/0nGenu5Ysj40wS8u –

+0

[Étroitement lié] (https://stackoverflow.com/questions/16708307/is-it-possible-to -galally-overload-a-string-literal-et-const-char), dupe possible. Qu'est-ce que tu penses? –

Répondre

8

Il ne se comporte pas comme prévu, il vous suffit d'ajuster vos attentes

const char[1] et const char (&)[1] sont les différents types. Les conversions const char* (conversion de tableau en pointeur) et const (&char)[1] (conversion d'identité) sont toutes deux considérées comme des correspondances exactes, mais un non-modèle correspond mieux qu'un modèle.

Si vous écrivez une surcharge spécifique de taille non-modèle,

void f(const char (&arg)[1]) 

vous obtiendrez une erreur que l'appel de fonction est ambiguë.

+2

Trop lent. :(Pour référence, le standardese pertinent est dans le tableau 12 dans N4141 –

1

La réponse de @ molbdnilo est correcte. Pour ajouter un détail: Votre intuition serait correcte et le compilateur préfèrerait éviter la conversion de tableau en pointeur en appelant le modèle. Mais les transformations de lvalue (lvalue à rvalue, tableau à pointeur, et fonction à pointeur) sont spécifiquement ignorées dans le classement de surcharge, selon [over.ics.rank] §13.3.3.2/3.2.1.

Il y a un workaround: ajouter un volatile faux pour rétablir l'équilibre de préférence de surcharge. Assurez-vous simplement de l'enlever par const_cast avant d'utiliser le paramètre.