2015-02-07 70 views
2

當我嘗試編譯使用lambda類型的變量模板的C++ 14代碼時,從Clang(3.4和3.5)中看到一個奇怪的錯誤。被調用的對象類型'auto'不是函數或函數指針

Here's the C++14 code as I'd like to write it.

Here's a second version,一些去除庫_t_v東西使編譯器高興:

#include <type_traits> 

template <class T> 
class forward_if_wrapper { 

    template <class U, class Enable = typename std::enable_if<std::is_lvalue_reference<U>::value>::type> 
    static U forward(U&& u) { 
     return u; 
    } 

    template <class U, class Enable = typename std::enable_if<!std::is_lvalue_reference<U>::value>::type> 
    static U&& forward(U&& t) { 
     return static_cast<U&&>(t); 
    } 
}; 
auto forward = [](auto&& t) { return forward_if_wrapper<decltype(t)>::forward(t); }; 
template <class T> auto forward_if = [](auto&& u) { return forward_if_wrapper<T>::forward(u); }; 

// -------- 

#include <stdio.h> 
#include <vector> 

template<class Elt> 
void bar(Elt&& e) { 
    printf("Called %s\n", __PRETTY_FUNCTION__); 
} 

template<class Container> 
void foo(Container&& c) { 
    for (auto&& elt : c) { 
     bar(forward_if<Container>(elt)); 
    } 
} 

int main() { 
    std::vector<int> v = {1,2}; 
    foo(v); 
    foo(std::move(v)); 
} 

我從鏘第二代碼中看到的錯誤是:

test.cc:34:13: error: called object type 'auto' is not a function or function pointer 
     bar(forward_if<Container>(elt)); 
      ^~~~~~~~~~~~~~~~~~~~~~~ 
test.cc:43:5: note: in instantiation of function template specialization 'foo<std::__1::vector<int, std::__1::allocator<int> > &>' requested here 
    foo(v); 
    ^

我沒有任何其他支持C++ 14通用lambdas的編譯器,所以Clan克是我測試過的。

這是我的錯誤還是叮噹的bug?

我傾向於認爲它是Clang模板實例化規則中的一個錯誤:Clang似乎將auto視爲類型世界中的一等公民,而不是作爲執行類型演繹的指標。

test.cc:34:14: error: invalid argument type 'auto' to unary expression 
     bar((+forward_if<Container>)(elt)); 
      ^~~~~~~~~~~~~~~~~~~~~~ 

還是那句話:

template<class T> T x{0}; // good 
template<class T> auto x = T{0}; // bad 

int main() 
{ 
    return x<int> + x<long>; 
} 

bad.cc:6:19: error: invalid operands to binary expression ('auto' and 'auto') 
+1

在你的問題的代碼片斷編譯罰款(後更改'class'到'struct'可訪問)與最新版本的鏗鏘++。這表明你看到的錯誤是一個已修復的編譯器錯誤。 – dyp 2015-02-07 19:42:16

+0

@dyp Hooray!你能告訴我'clang --version'的輸出嗎?理想情況下,我想找到一個在線服務,如ideone或godbolt,支持該版本的Clang。 (http://ideone.com/jRZ5SD甚至不支持變量模板。) – Quuxplusone 2015-02-07 20:24:34

+0

[melpon.org/wandbox](http://melpon.org/wandbox)通常具有非常新的g ++和clang ++版本,但我不確定您是否可以將編譯器開關調整爲合理的值(如'-std = C++ 1y') - 編輯:啊,您可以在頁面左下方調整它。 [coliru.stacked-crooked.com](http:// http://coliru.stacked-crooked.com/)也具有g ++和clang ++的合理近期版本。我已經使用了一個鏗鏘聲3.7.0版本(中繼線228504),它應該是中繼端的atm。 – dyp 2015-02-07 20:33:11

回答

0

每@ DYP的和@ ildjarn的評論:是的,這是鏘3.4(也許3.5)中的錯誤。它在Clang 3.7.0(也許更早)中是固定的。在Wandbox上有各種版本的Clang。

而且here is the C++14 code I was trying to construct!

#include <type_traits> 

template <class T> 
struct forward_wrapper { 

    template <class U, class Enable = std::enable_if_t<(sizeof(std::remove_reference<U>), std::is_reference<T>::value)>> 
    static U forward(U&& u) { 
     return u; 
    } 

    template <class U, class Enable = std::enable_if_t<(sizeof(std::remove_reference<U>), !std::is_reference<T>::value)>> 
    static decltype(auto) forward(U&& u) { 
     return static_cast<typename std::remove_reference<U>::type &&>(u); 
    } 
}; 

template <class T> auto forward = 
    [](auto&& u) -> decltype(auto) { return forward_wrapper<T>::forward(u); }; 

// -------- 

#include <stdio.h> 
#include <vector> 

void bar(int &) { puts("Called copy function"); } 
void bar(int &&) { puts("Called move function"); } 

template<class Container> 
void foo(Container&& c) { 
    for (auto&& elt : c) { 
     bar(forward<Container>(elt)); 
    } 
} 

int main() { 
    std::vector<int> v = {1,2}; 
    foo(v); 
    foo(std::move(v)); 
} 
相關問題