Почему код, использующий локальную структуру в качестве параметра для функции STL, не компилируется в g ++? - PullRequest
11 голосов
/ 31 декабря 2010

У меня есть такой код, который хорошо работает:

#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;
}

Но если я изменю его на этот стиль:

#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;
}

Он не скомпилируется, говоря:

ошибка: нет соответствующей функции для вызова 'transform (char [11], char *, char [11], main () :: F)'

Что не так?

gcc версия 4.4, которая не распознает лямбда-выражения.

Ответы [ 2 ]

10 голосов
/ 31 декабря 2010

В C ++ - 98/03 второй код недействителен, так как F является локальным типом; на самом деле в §14.3.1.2 указано, что

Локальный тип, тип без связывания, безымянный тип или тип, составленный из любого из этих типов, не должны использоваться в качестве аргумента шаблона для параметра типа шаблона.

[Пример:

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
}

- конец примера] [Примечание: аргумент типа шаблона может быть неполного типа (3.9). ]

В C ++ - 0x это ограничение снято; в том же разделе новый стандартный проект (N3126) явно показывает это в примере:

[Пример:

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
}

- конец примера] [Примечание: аргумент типа шаблона может быть неполного типа (3.9). - конец примечания]

4 голосов
/ 31 декабря 2010

g ++ 4.5.1 компилирует ваш код (с опцией -std=c++0x).

Ваш второй пример кода некорректен в C ++ 03 1 , но действителен в C ++ 0x

std::transform равен

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

Однако g ++ 4.4 не поддерживает локальные типы в качестве аргументов шаблона (даже с параметром - std=c++0x), поэтому вы получаете ошибку.

1: локальный тип,тип без связывания, безымянный тип или тип, составленный из любого из этих типов, не должен использоваться в качестве аргумента шаблона для параметра типа шаблона (ISO C ++ 03 §14.3.1.2)

...