2014-10-08 1 views
1

Я использую CRTP для реализации чего-либо, но я застрял на ошибке в XCode 4.5.2. Следующий код представляет собой упрощенную версию, которая все еще реплицирует ошибку. Это происходит на линии, где метод Api::Enable определен и имеет что-то делать с тем фактом, что не существует никаких параметров при Api::Enable вызовов this->T::EnableОшибка CRTP с XCode 4.5.2 - Parse Issue, ожидаемое выражение

enum Enum 
{ 
    FOO, 
    BAR, 
    BAZ, 
}; 

template <typename T> 
class Api 
{ 
public: 
    template <Enum E, bool On> void Enable() {static_cast<T *>(this)->Enable<E, On>();} 
}; 

class ApiImpl : public Api<ApiImpl> 
{ 
public: 
    template <Enum E, bool On> void Enable() {} 
}; 

int main(int argc, const char * argv[]) 
{ 
    ApiImpl clsApi; 
    clsApi.Enable<FOO, true>(); 
    return 0; 
} 

Вот скриншот ошибки в Xcode: http://i.imgur.com/IxEOgQ6.png. Я получаю ту же ошибку, пользуюсь ли я «компилятором Apple LLVM 4.1» или «LLVM GCC 4.2». MSVC Express 2010 компилируется без ошибок.

Обратите внимание, что добавление параметра функции приводит к исчезновению ошибки. Следующие отлично компилируется:

enum Enum 
{ 
    FOO, 
    BAR, 
    BAZ, 
}; 

template <typename T> 
class Api 
{ 
public: 
    template <Enum E , bool On> void Enable(unsigned int X) {static_cast<T *>(this)->Enable<E, On>(X);} 
}; 

class ApiImpl : public Api<ApiImpl> 
{ 
public: 
    template <Enum E, bool On> void Enable(unsigned int) {} 
}; 

int main(int argc, const char * argv[]) 
{ 
    ApiImpl clsApi; 
    clsApi.Enable<FOO, true>(0); 
    return 0; 
} 

ответ

1

Вы должны использовать ключевое слово template разрешить зависимые имена шаблона:

template <Enum E, bool On> void Enable() { 
    static_cast<T*>(this)->template Enable<E, On>(); 
} 

C++ 11, [temp.names]/4:

When the name of a member template specialization appears after . or -> in a postfix-expression or after a nested-name-specifier in a qualified-id, and the object expression of the postfix-expression is type-dependent or the nested-name-specifier in the qualified-id refers to a dependent type, but the name is not a member of the current instantiation (14.6.2.1), the member template name must be prefixed by the keyword template. Otherwise the name is assumed to name a non-template.

Если Enable(), например, template <typename T> void Enable(){} , то clang показывает ошибку: error: use 'template' keyword to treat 'Enable' as a dependent template name.

Я не знаю, почему он создает это нерелевантное сообщение в вашем случае (когда аргументы шаблона не являются типами). Я думаю, что это можно опубликовать как отчет об ошибке. (Я тестировал на clang 3.6 - то же самое).

Кроме того, gcc 4.8 и 4.9 не содержат ошибок в этом коде, который я верю, также неверен.