2017-04-20 2 views
3
#include <iostream> 

using namespace std; 

template<const int arr[]> 
struct S { 
    static constexpr int value = arr[0]; 
}; 

constexpr int arr[] = { 5 }; 

int main() { 
    cout << S<arr>::value << endl; 
} 

Ce programme compile bien et imprime 5 avec gcc 5.1 et plus, mais MSVC 19.10.25019 donne les erreurs suivantes:utilisation du tableau constexpr comme argument non type de modèle (C++ 14)

erreur C2975: « S »: argument modèle invalide pour arr ', attendu erreur d'expression constante compilation C2131: expression n'a pas à une

évaluer constante

ce programme est valide selon la C++ 14 Standard, ou gcc est trop indulgent ici?

+0

Pour l'enregistrement, Clang accepte également ce code. – jwimberley

+0

Que dit MSVC si vous remplacez 'arr []' par 'arr [1]'? – jwimberley

+0

@jwimberley Ça ne change rien. –

Répondre

2

Le programme est bien formé autant que je peux voir.

Selon [temp.param]/8, le paramètre de modèle a réellement le type const int*, et non const int[].

A non de type modèle-paramètre de type « réseau de T » ou « fonction renvoyant T » est ajusté comme étant de type « pointeur vers T » ou « pointeur de fonction retournant T », respectivement .

Selon [temp.arg.nontype]/1, on peut utiliser le nom d'un objet tableau complet avec la durée de stockage statique et une liaison externe comme un argument à un tel paramètre de modèle:

a pour un non-type de modèle argument , non-modèle modèle-paramètre doit être:

...

- const expression ant (5.19) qui désigne l'adresse d'un objet complet avec durée de stockage statique et liaison externe ou interne ou une fonction avec liaison externe ou interne, y compris la fonction modèles et la fonction ID de modèle mais en excluant les membres de classe non statiques, exprimés (entre parenthèses en ignorant) comme &id-expression, où l'id expression est le nom d'un objet ou d'une fonction, à l'exception que le & peut être omis si le nom fait référence à une fonction ou un tableau et doit être omis si le paramètre de modèle correspondant est une référence ...

arr est une expression constante, malgré le fait que MSVC pense que ce n'est pas le cas. C'est une expression constante de base selon [expr.const]/2 car elle ne contient aucune évaluation interdite, et c'est une expression constante car elle pointe vers un objet avec une durée de stockage statique ([expr.const]/4). Comme le paramètre de modèle fait référence à un tableau avec une durée de stockage statique, les limites du tableau sont connues au moment de l'instanciation du modèle. Il peut donc vérifier que l'accès à arr[0] est une expression de base constante car il a un comportement bien défini et entre dans la catégorie des conversions lvalue-à-rvalue autorisées dans [expr.const]/2:

... un glvalue non volatile du type intégral ou énumération qui se réfère à un objet const non volatile avec une initialisation précédentes, initialisé avec une expression constante

+0

Techniquement, il ne respecte pas [temp.arg.nontype] /2.1: "Pour un paramètre de type pointeur non-type de ..., la valeur de l'expression constante ne doit pas ... être l'adresse de ... a sous-objet ". Le pointeur pointe vers le premier élément du tableau, qui est un sous-objet. Mais c'est un problème connu avec le libellé actuel; Voir CWG 2043. –