les fonctions constexpr
ne sont pas censées contenir:
Une définition d'une variable de type non littéral
Mais dans cette réponse, un lambda est défini en un seul: https://stackoverflow.com/a/41616651/2642059
template <typename T>
constexpr auto make_div(const T quot, const T rem)
{
return [&]() {
decltype(std::div(quot, rem)) result;
result.quot = quot;
result.rem = rem;
return result;
}();
}
et dans mon commentaire je définis un div_t
en un: Comment puis-je initialiser un objet div_t?
template <typename T>
constexpr decltype(div(T{}, T{})) make_div(const T quot, const T rem)
{
decltype(div(T{}, T{})) x{};
x.quot = quot;
x.rem = rem;
return x;
}
Qu'entend-on exactement par l'interdiction de la "définition d'une variable de type non littéral"?
Visual Studio 2015 ne permettra pas ma définition d'un div_t
mais je trouve absurde qu'il soit permis d'envelopper un tel comportement illégitime dans un lambda et de l'exécuter. Je voudrais savoir lequel si l'un des compilateurs se comporte correctement par rapport au div_t
définition.
Il est pratiquement garanti que s'il y a une anomalie, gcc a le comportement correct, car Visual Studio 2015 ne prend pas en charge c ++ 14 l'extension de constexpr
: https: //msdn.Microsoft.com/en-us/library/hh567368.aspx#C-14-Core-Language-Features
constexpr
Le corps de la fonction peut uniquement contenir:
- instructions null (points-virgules simples)
static_assert
Déclarationstypedef
déclarations et déclarations d'alias qui ne définissent pas de classes ou d'énumérationsusing
déclarationsusing
directives- exactement une instruction
return
Donc c ++ 11 ne peut pas tolérer la définition de decltype(div(T{}, T{})) x{}
. Il serait cependant acceptable de rouler le ternaire suggéré ici dans une fonction constexpr
pour obtenir les mêmes résultats:
template <typename T>
constexpr auto make_div(const T quot, const T rem)
{
using foo = decltype(div(T{}, T{}));
return foo{1, 0}.quot != 0 ? foo{quot, rem} : foo{rem, quot};
}
constexpr
Le corps de la fonction peut contenir autre chose que :
- une déclaration asm
- une déclaration goto
- une instruction avec une étiquette autre que case et default
- un bloc d'essai
- une définition d'une variable de type non littéral
- une définition d'une variable de durée de stockage statique ou de thread
- une définition d'une variable pour laquelle aucune initialisation n'est effectuée
Lorsqu'un "type littéral" est défini ici , spécifiquement pour les objets cependant, ils peuvent être des types agrégés avec un destructeur trivial. Donc div_t
Est définitivement admissible. Ainsi c ++ 14 , et par extension gcc, peut tolérer la définition de decltype(div(T{}, T{})) x{}
.
constexpr
C++ 17 a ajouté la prise en charge des types de fermeture à la définition de "Literal Type", donc je trouve étrange que gcc et Visual Studio prennent en charge l'utilisation du lambda dans l'instruction return
. Je suppose que c'est soit un support prospectif, soit le compilateur a choisi d'intégrer le lambda. Dans les deux cas, je ne pense pas que cela puisse être considéré comme une fonction c ++ 14constexpr
.
[ Source ]