2016-06-23 106 views
0

更新:我簡化了這個問題的代碼,並刪除了原始的,更復雜的代碼。C++運算符<<編譯錯誤與gtest AssertionFailure

請幫我理解是什麼導致我在下面描述的錯誤。

我已經定義了一個簡單的4xfloat矢量類型Vector4f。現在我只定義了索引運算符,但是最終我將定義運算符用於加,減等。我還定義了一個流運算符,用於將矢量序列化爲流。這個操作符只使用公共方法,所以它不是friendVector4f

vector.h:

#ifndef VECTOR_HPP 
#define VECTOR_HPP 

namespace vector { 

class Vector4f { 
public: 
    Vector4f(float x0, float x1, float x2, float x3) : 
    storage_({x0, x1, x2, x3}) {} 

    float & operator[](size_t i) { return storage_[i]; } 
    const float & operator[](size_t i) const { return storage_[i]; } 

protected: 
    typedef std::vector<float> StorageType; 
    StorageType storage_; 
}; 

template <typename StreamType> 
StreamType & operator<<(StreamType & s, const Vector4f & v) { 
    return s << "[ " << v[0] << ", " << v[1] << ", " << v[2] << ", " << v[3] << " ]"; 
} 

} // namespace vector 

#endif // VECTOR_HPP 

我正在與C++ 11(鐺)編譯。流序列模板似乎對ostream的工作:

std::cout << vector::Vector4f(1,2,3,4) << std::endl; // compiles 

在哪裏我遇到的問題是GoogleTest的AssertionFailure類,可與流運算符可以用來添加信息。我正在尋找最終使用幫助函數來檢查矢量是否包含我期望的值(而不依賴於尚不存在的相等運算符)。爲簡單起見,我使用的是直接斷言這裏:

test_vector.cc:

#include <gtest/gtest.h> 
#include "vector.h" 

class TestVector : public ::testing::Test {}; 

TEST_F(TestVector, ctor_by_float_parameters) { 
    vector::Vector4f v(0.0f, 0.1f, 0.2f, 0.3f); 
    EXPECT_TRUE(::testing::AssertionFailure() << v); 
} 

編譯器失敗,此錯誤:

In file included from test_vector2.cc:2: 
./vector2.h:21:10: error: non-const lvalue reference to type 'std::__1::basic_stringstream<char, 
     std::__1::char_traits<char>, std::__1::allocator<char> >' cannot bind to a value of unrelated type 
     'basic_ostream<char, std::__1::char_traits<char> >' 
    return s << "[ " << v[0] << ", " << v[1] << ", " << v[2] << ", " << v[3] << " ]"; 
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
googletest/include/gtest/gtest-message.h:131:10: note: in instantiation of function template specialization 
     'vector::operator<<<std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> > >' 
     requested here 
    *ss_ << val; 
     ^
googletest/include/gtest/gtest.h:306:29: note: in instantiation of function template specialization 
     'testing::Message::operator<<<vector::Vector4f>' requested here 
    AppendMessage(Message() << value); 
          ^
test_vector2.cc:10:45: note: in instantiation of function template specialization 
     'testing::AssertionResult::operator<<<vector::Vector4f>' requested here 
    EXPECT_TRUE(::testing::AssertionFailure() << v); 

從我的理解,它是有麻煩將我的Vector類的operator<<模板的結果應用於測試:: AssertionFailure類的operator<<。我不明白爲什麼這會導致一個問題,因爲它應該在將我的向量序列化爲一個stringstream之後調用AssertionFailure的操作符。這裏有一些我還不明白的東西,我當然不明白錯誤信息本身。

任何幫助表示讚賞,請。

+2

這對我來說太多的信息。請發佈[最小,完整和可驗證示例](http://stackoverflow.com/help/mcve)。 –

+0

@RSahu好的,謝謝你的建議。我用更簡單的版本更新了我的問題,該版本顯示相同的編譯器錯誤。 – meowsqueak

+1

我不明白爲什麼你的'operator <<'函數必須是一個模板,不能只使用類'std :: ostream'。這可能會一直解決問題。 –

回答

2
return s << "[ " << v[0] << ", " << v[1] << ", " << v[2] << ", " << v[3] << " ]"; 

應該是

s << "[ " << v[0] << ", " << v[1] << ", " << v[2] << ", " << v[3] << " ]"; 
return s; 

這是因爲operator<<(float)成員函數的std::basic_ostream。它返回std::basic_ostream<...>&,而不是您調用它的流的類型。您不能將其轉換爲StreamType&,除非StreamType碰巧是basic_ostreamstd::cout就是這種情況。

另外,聲明你operator<<作爲

template <typename VectorType, typename... StreamArgs> 
std::basic_ostream<StreamArgs...> & 
operator << (std::basic_ostream<StreamArgs...>& s, 
       const BaseVector<VectorType> & v) 
+0

謝謝 - 第一個建議爲我解決了這個問題,但是我也會閱讀可變參數模板參數,以便我能理解你的第二個建議。 – meowsqueak

+0

你知道爲什麼用'std :: ostream'替換'StreamType'會導致編譯器錯誤,我在其中一個註釋中提到了我的問題?根據你所解釋的,我會預料到這是可行的,因爲'std :: ostream'是一個'basic_ostream '。 – meowsqueak

+0

@meowsqueak我無法重現該錯誤。您可能在其他地方有錯誤。但不建議使用此解決方案。如果有人使用'std :: wostream',或者使用非默認分配器,或者其他什麼? –