Passer des objects constexpr autour

J’ai décidé de constexpr ensuite la nouvelle définition de constexpr C++14 et d’en tirer le meilleur parti, j’ai décidé d’écrire un petit parsingur de chaîne au moment de la compilation. Cependant, j’ai du mal à garder mon object comme constexpr tout en le passant à une fonction. Considérons le code suivant:

 #include  #include  class str_const { const char * const p_; const std::size_t sz_; public: template  constexpr str_const( const char( & a )[ N ] ) : p_( a ), sz_( N - 1 ) {} constexpr char operator[]( std::size_t n ) const { return n < sz_ ? p_[ n ] : throw std::out_of_range( "" ); } constexpr std::size_t size() const { return sz_; } }; constexpr long int numOpen( const str_const & str ){ long int numOpen{ 0 }; std::size_t idx{ 0 }; while ( idx < str.size() ){ if ( str[ idx ] == '{' ){ ++numOpen; } else if ( str[ idx ] == '}' ){ --numOpen; } ++idx; } return numOpen; } constexpr bool check( const str_const & str ){ constexpr auto nOpen = numOpen( str ); // ... // Apply More Test functions here, // each returning a variable encoding the correctness of the input // ... return ( nOpen == 0 /* && ... Test the variables ... */ ); } int main() { constexpr str_const s1{ "{ Foo : Bar } { Quooz : Baz }" }; constexpr auto pass = check( s1 ); } 

J’utilise la classe str_const présentée par Scott Schurr à C ++ Now 2012 dans une version modifiée pour C++14 .

Le code ci-dessus ne pourra pas être compilé avec l’erreur ( clang-3.5 )

 error: constexpr variable 'nOpen' must be initialized by a constant expression constexpr auto nOpen = numOpen( str ); ~~~~~~~~~^~~~~ 

Ce qui m’amène à la conclusion que vous ne pouvez pas contourner un object constexpr sans perdre son constexpr constexpr. Cela m’a amené aux questions suivantes:

  1. Mon interprétation est-elle correcte?
  2. Pourquoi est-ce le comportement que la norme dicte?

    Je ne vois pas le problème en passant un object constexpr autour. Bien sûr, je pourrais réécrire mon code pour l’intégrer à une seule fonction, mais cela conduit à un code exigu. Je suppose que la factorisation de fonctionnalités distinctes dans des unités de code (fonctions) distinctes devrait également constituer un bon style pour les opérations de compilation.

  3. Comme je l’ai dit précédemment, l’erreur du compilateur peut être résolue en déplaçant le code des corps de fonctions de test distinctes (telles que numOpen ) dans le corps de la check fonction de niveau supérieur. Cependant, je n’aime pas cette solution car elle crée une fonction énorme et exiguë. Voyez-vous une approche différente pour résoudre le problème?

La raison en est que, dans une fonction constexpr , les parameters ne sont pas des expressions constantes , que les arguments soient ou non. Vous pouvez appeler des fonctions constexpr l’intérieur d’autres personnes, mais les parameters d’une fonction constexpr ne sont pas constexpr intérieur , rendant tout appel de fonction (même aux fonctions constexpr ) pas une expression constante – à l’ intérieur .

 const auto nOpen = numOpen( str ); 

Suffices Une fois que vous visualisez l’appel de l’ extérieur de la constexpr -ness des expressions à l’intérieur, il est vérifié, décidant si l’appel entier est constexpr ou non.