2017-01-18 3 views
1

У меня есть класс с шаблонизированной функцией-членом, которая принимает вызываемый тип в качестве аргумента и имеет тип возвращаемого значения, выводимый из возвращаемого типа поставляемая функция с использованием decltype с синтаксисом типа возвращаемого типа возврата. Ниже приведен минимальный пример.ошибка компилятора в gcc, но не clang при использовании decltype с templated member function с типом возвращаемого типа возвращаемого значения

#include <iostream> 
#include <vector> 

class point { 
    public: 
     std::vector<double> val; 
     point(double in) : val({in}) {}; 
     template<typename T> auto eval(const T& in) -> decltype(in(val[0])); 
}; 

template<typename T> 
auto point::eval(const T& in) -> decltype(in(val[0])){ 
    return in(val[0]); 
} 

int main(int argc, char *argv[]){ 

    point pt(2.0); 
    auto f = [](double x){return x*x;}; 

    std::cout << pt.val[0] << std::endl; 
    std::cout << pt.eval(f) << std::endl; 
} 

Этот код компилируется и работает, как ожидалось в звоном ++ и г ++ - 5, но дроссели со следующей ошибкой в ​​г ++ - 6.

> g++-6 main.cpp -o test -std=c++11 -Wall main.cpp:13:6: error: 
> prototype for 'decltype 
> (in(0->((point*)this)->point::val.std::vector<_Tp, 
> _Alloc>::operator[]<double, std::allocator<double> >())) point::eval(const T&)' does not match any in class 'point' auto 
> point::eval(const T& in) -> decltype(in(val[0])){ 
>  ^~~~~ main.cpp:9:35: error: candidate is: template<class T> decltype (in(0->((point*)this)->point::val.std::vector<_Tp, 
> _Alloc>::operator[]<double, std::allocator<double> >())) point::eval(const T&) 
>   template<typename T> auto eval(const T& in) -> decltype(in(val[0])); 
>         ^~~~ main.cpp:9:35: error: 'decltype (in(0->((point*)this)->point::val.std::vector<_Tp, 
> _Alloc>::operator[]<double, std::allocator<double> >())) point::eval(const T&) [with T = main(int, char**)::<lambda(double)>; 
> decltype (in(0->((point*)this)->point::val.std::vector<_Tp, 
> _Alloc>::operator[]<double, std::allocator<double> >())) = double]', declared using local type 'const main(int, char**)::<lambda(double)>', 
> is used but never defined [-fpermissive] main.cpp:9:35: warning: 
> 'decltype (in(0->((point*)this)->point::val.std::vector<_Tp, 
> _Alloc>::operator[]<double, std::allocator<double> >())) point::eval(const T&) [with T = main(int, char**)::<lambda(double)>]' 
> used but never defined make: *** [all] Error 1 

Ошибка компилятора не отображается, если реализация написана рядный, т.е.

template<typename T> auto eval(const T& in) -> decltype(in(val[0])){ 
      return in(val[0]); 
} 

Кроме того, в C++ 14 с использованием автоматического типа возврата дедукции путем изменения подписи

template<typename T> auto eval(const T& in); 

работает должным образом.

Является ли это ошибкой компилятора gcc или неверно принимает вышеуказанный код? Что делать, если какая-либо разница между этими сигнатурами функций? Почему встраивание реализации имеет значение?

+1

Несомненно, ошибка gcc. – ildjarn

ответ

1

Да, вероятно, ошибка gcc. Обходной путь

template<typename T> 
std::result_of<T(double)> point::eval(const T& in) { 
-2

Это связано с тем, что вы явно не определяете определение функции шаблона. Насколько я понимаю, это недопустимый код C++, и компиляторы не должны его принимать. Если вы хотите воспроизвести эту ошибку на других компиляторах, попробуйте переместить класс point в файл заголовка и определение point::eval в файл .cpp. Таким образом, у вас либо есть explicitly instantiate это определение для каждого типа аргумента (что невозможно с lambdas), либо (как я полагаю) не используют шаблоны вне очереди, если это не требуется срочно.

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