簡體   English   中英

在將decltype與帶有尾隨返回類型語法的模板化成員函數一起使用時,gcc中出現編譯器錯誤,但沒有clang

[英]compiler error in gcc but not clang when using decltype with templated member function with trailing return type syntax

我有一個帶有模板成員函數的類,該成員函數采用可調用類型作為參數,並具有使用尾隨返回類型語法使用decltype從提供的函數的返回類型中推導的返回類型。 一個最小的例子如下所示。

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

此代碼可在clang ++和g ++-5中按預期方式編譯和運行,但在g ++-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編譯器錯誤還是clang錯誤地接受了上面的代碼? 這些功能簽名之間的區別是什么? 為什么內聯實現會有所作為?

是的,可能是gcc錯誤。 解決方法是

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

那是因為您沒有顯式實例化模板函數定義。 據我了解,這不是有效的c ++代碼,編譯器不必接受它。 如果要在其他編譯器上重現此錯誤,請嘗試將point類移至頭文件, point::eval定義移至.cpp文件。 因此,您要么必須為每種類型的參數顯式實例化此定義(lambdas不可能),要么(如我建議的那樣)除非緊急需要,否則不要使用離線模板。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM