2013-10-28 3 views
1

Я создал класс, выглядящий примерно так. Ключ в том, что у него есть основной аргумент шаблона плюс базовый класс шаблона со значением по умолчанию. Существует также шаблонный конструктор копирования ...Наследование из шаблона класса с аргументом по умолчанию

struct default_base{}; 

template <typename T, typename TBase=default_base> 
class some_class : public TBase{ 
public: 
    some_class(){} 
    template <typename U, typename UBase> 
    some_class(const some_class<U,UBase>& u){ 
     T t(U()); 
    } 
}; 


int main(){ 
    some_class<int> a; 
    return 0; 
} 

Я получаю это раздражающе смутное ошибку компилятора, так и не смогли обнаружить свою ошибку ... поэтому мой вопрос - что это на самом деле так? Я использую gcc 4.8.1.

g++ -O0 -g3 -Wall -c -fmessage-length=0 -o "src\\stuff.o" "..\\src\\stuff.cpp" 
..\src\stuff.cpp: In constructor 'some_class<T, TBase>::some_class(const some_class<U,  UBase>&)': 
..\src\stuff.cpp:87:10: error: default argument for template parameter for class  enclosing 'T t(U (*)())' 
    T t(U()); 
    ^
..\src\stuff.cpp: In function 'int main()': 
..\src\stuff.cpp:104:16: error: wrong number of template arguments (1, should be 2) 
    some_class<int> a; 
      ^
..\src\stuff.cpp:82:7: error: provided for 'template<class T, class TBase> class some_class' 
class some_class : public TBase{ 
^
..\src\stuff.cpp:104:19: error: invalid type in declaration before ';' token 
    some_class<int> a; 

Edit: Пятно на ответы, ура :-) Даже если я все еще думаю, что он должен составить ... это компилирует ...

template <typename T> 
struct some_other_class{ 
some_other_class(){} 
    template <typename U> 
    some_other_class(){ 
     T t(U()); 
    } 
}; 

ответ

7
T t(U()); 

Это так называемый "most vexing parse". Это объявление функции, которое возвращает T, и принимает нулевую функцию, которая возвращает U как параметр. Представьте себе:

typedef U nullary_function_return_U(); 
T t(nullary_function_return_U /*param_name*/) 
{ 
    return T; 
} 

Вы можете обойти это путем добавления скобок:

T t((U())); 

Или в C++ 11, вы можете использовать однородный синтаксис инициализации:

T t{U{}}; 

самое неприятное. Сообщение об ошибке действительно ужасно и независимо от самого досадного разбора, Должна ли она компилироваться, не так ли?

Я тестировал GCC 4.8.1 - Ошибка, Clang 3.4 - OK, MSVC2010 - ОК. Я вырубить его наименьший случай, который вызывает ошибку на GCC:

template <typename = int> 
struct Foo 
{ 
    Foo() 
    { 
     int t(int()); // Error 
    } 
}; 

int main() 
{ 
    int t(int()); // OK 
    Foo<> a; // Error 
} 

Это выглядит как GCC ошибка. Я сделал отчет до GCC Bugzilla.


Edit:

Карлини 2014-07-07 14:11:14 UTC Это уже исправлена ​​магистраль и 4.9.1. Я добавляю тест и закрываю ошибку.

+0

Самое неприятное действительно. Сообщение об ошибке действительно ужасно и независимо от самого досадного разбора, оно должно действительно скомпилироваться, не так ли? – Magnus

+0

@Magnus см. Мое редактирование - это похоже на ошибку GCC. Я открыл билет в GCC Bugzilla. –

+0

Cheers, Это довольно неясная комбинация, поэтому я не удивлен ошибкой. – Magnus

1

Вы действительно хотите, чтобы объявить функцию с именем t, принимая функцию, возвращающую U в качестве аргумента, и возвращающегося T? Когда неоднозначности декларации объявить переменную t с использованием, например,

T t{U()}; 

кажется НКА довольна decaration.

+0

Я этого не делаю, это действительно самый неприятный синтаксический разбор, но если да, то какова фактическая ошибка? – Magnus

+1

@Magnus: возможно, что-то внутреннее для gcc: clang счастливо компилирует исходный код (хотя и с предупреждением о объявляемой функции). –

+0

я что-то подобное btemplate STRUCT some_other_class заподозрить { \t some_other_class() {} \t шаблон \t some_other_class() { \t \t T T (U()); \t} }; – Magnus

Смежные вопросы