11

I have such code which works well:

#include <algorithm>
#include <iostream>

char x[11]= "ABCDEFGHIJ";
char y[11];

struct F {
    char operator () (char c) const 
    { return c+1; }
};

int main()
{
    std::transform(x, x+10, y, F());
    y[10] = 0; std::cout <<y <<std::endl;
}

But if I change it to this style:

#include <algorithm>
#include <iostream>

char x[11]= "ABCDEFGHIJ";
char y[11];

int main()
{
    struct F {
        char operator () (char c) const 
        { return c+1; }
    };
    std::transform(x, x+10, y, F());
    y[10] = 0; std::cout <<y <<std::endl;
}

It will not compile, saying:

error: no matching function for call to ‘transform(char [11], char*, char [11], main()::F)’

What's wrong?

gcc version is 4.4, which does not recognize lambda expressions.

Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345
RnMss
  • 3,696
  • 3
  • 28
  • 37

2 Answers2

10

In C++-98/03 the second code is not valid, since F is a local type; in facts, at §14.3.1.2 it's stated that

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.

[Example:

template <class T> class X { /* ... */ };
void f()
{
    struct S { /* ... */ };
    X<S> x3;         // error: local type used as template-argument
    X<S*> x4;        // error: pointer to local type used as template-argument
}

—end example] [Note: a template type argument may be an incomplete type (3.9). ]

In C++-0x this limitation is removed; in the same section, the new standard draft (N3126) explicitly shows this in the example:

[ Example:

template <class T> class X { };
template <class T> void f(T t) { }
struct { } unnamed_obj;

void f() {
    struct A { };
    enum { e1 };
    typedef struct { } B;
    B b;
    X<A> x1;             // OK
    X<A*> x2;            // OK
    X<B> x3;             // OK
    f(e1);               // OK
    f(unnamed_obj);      // OK
    f(b);                // OK
}

— end example ] [ Note: a template type argument may be an incomplete type (3.9). — end note ]

Community
  • 1
  • 1
Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
  • 1
    We're in C++03 or C++0x, not C++98 anymore. Of course, the point is still valid, but quoting from an outdated Standard is meaningless. – Puppy Dec 31 '10 at 12:09
  • @DeadMG: unfortunately I couldn't find a free draft of C++03, so I have to stick to C++98 for quotations `:(` ; still, I checked the unofficial list of changes and §14.3 is not included in the changes, so the quotation should be still valid for C++03. – Matteo Italia Dec 31 '10 at 12:15
  • I see ... do you know why such limitation came about? – RnMss Dec 31 '10 at 12:42
  • There is no such thing as C++03. There is exactly one C++ Standard in existence at this time (C++98 if you like). C++0x which will actually be more like C++11 may become a standard soon but it isn't yet. – Yttrill Dec 31 '10 at 15:12
  • @Yttrill: Yes, there is. C++03 refers to ISO/IEC 14882:2003(E), which is the current C++ Standard (it replaced the C++98 Standard). – James McNellis Dec 31 '10 at 17:47
  • 3
    @Yttrill Hmm, I thought so too. But looking up, it seems that C++03 isn't actually a TC, but a completely new version of C++. This seems to be contradicted by GCC and Clang though, which only have -std=c++98 and say "The 1998 ISO C++ standard plus amendments. Same as -ansi for C++ code.". Weird! – Johannes Schaub - litb Jan 01 '11 at 04:49
4

g++ 4.5.1 compiles your code (with -std=c++0x option).

Your second code sample is ill-formed in C++031 but valid in C++0x

std::transform is

template < class InputIterator, class OutputIterator, class UnaryOperator >
  OutputIterator transform ( InputIterator first1, InputIterator last1,
                             OutputIterator result, UnaryOperator op );

However g++ 4.4 doesn't support local types as template arguments (even with -std=c++0x option] so you get an error.

1 : 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. (ISO C++03 §14.3.1.2)

Prasoon Saurav
  • 91,295
  • 49
  • 239
  • 345