Thursday, April 28, 2011

Using local classes with STL algorithms

I have always wondered why you cannot use locally defined classes as predicates to STL algorithms.

In the question: Approaching STL algorithms, lambda, local classes and other approaches, BubbaT mentions says that 'Since the C++ standard forbids local types to be used as arguments'

Example code:

int main() {
   int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
   std::vector<int> v( array, array+10 );

   struct pair : public std::unary_function<int,bool>
   {
      bool operator()( int x ) { return !( x % 2 ); }
   };
   std::remove_if( v.begin(), v.end(), pair() ); // error
}

Does anyone know where in the standard is the restriction? What is the rationale for disallowing local types?

From stackoverflow
  • It's explicitly forbidden by the standard.

    C++0x will remove that restriction.

    To be more complete :

    The restrictions on types that are used as template parameters are listed in article 14.3.1 of the C++03 (and C++98) standard:

    A local type, a type with no linkage, an unnamed type or a type compounded from any of these types shall not be used as a template-argument for a template type-parameter.

    template <class T> class Y { /* ... */  }; 
    void func() {   
          struct S { /* ... */ }; //local class   
          Y< S > y1; // error: local type used as template-argument  
          Y< S* > y2; // error: pointer to local type used as template-argument }
    

    Source and more details : http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=420

    To sum up, the restriction was a mistake that would have been quickly fixed if the standard was evolving faster...

    David Rodríguez - dribeas : I know, but I'd like to know where to see if I can understand why. Do you have a reference into the standard?
    greyfade : Are you referring to 14.3.1.2, "template type arguments"?
    Klaim : I added some informations and a link that might help. To sum up, the restriction was a mistake that would have been quickly fixed if the standard was evolving faster...
    Robert Gould : But as an ISO standard it can't, by the ISO rules, evolve any faster than in 10 year periods. So for example 98 standard existed, so C++0x couldn't come out before 2008, and by the looks of it we won't have a C++1x, but a C++21 or something like that. ISO standards are too slow...
    Klaim : ISO rules enforce 10 years periods? Really? If that's true, it's a real pain in the arse. Stroustrup suggested in his faq that the next standard should come in a shorter time...
  • The restriction will be removed in '0x, but I don't think you'll be using them very much. And that's because C++-0x is going to have lambdas! :)

    int main() {
       int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
       std::vector<int> v( array, array+10 );
    
       std::remove_if( v.begin()
                     , v.end()
                     , [] (int x) -> bool { return !(x%2); })
    }
    

    My syntax in the above may be not be perfect, but the general idea is there.

    David Rodríguez - dribeas : I knew about lambdas. In fact, what I wanted to achieve is the closest possible with the current standard. Kind of the solution Java proposes.

0 comments:

Post a Comment

Note: Only a member of this blog may post a comment.