2016-08-20 19 views
10

Tôi đang sử dụng Google thử nghiệm v1.7Google thử nghiệm không thể tìm thấy người dùng được cung cấp bình đẳng điều hành

tôi đã tạo ra một phong tục operator ==ASSERT_EQ không thể tìm thấy, nhưng có thể được tìm thấy nếu sử dụng trực tiếp. Dưới đây là đoạn code

#include <vector> 
#include <deque> 

#include "gtest/gtest.h" 

template< typename T> struct bar { T b; }; 

template< typename T> 
bool operator == (const std::vector<T>& v, const bar<T>& b) { return false; } 

template< typename T> 
bool operator==( const std::vector<T>& v , const std::deque<T>& d) { return false; } 

TEST(A, B) { 

    std::vector<char> vec; 
    std::deque<char> deq; 
    bar<char> b; 

    // compiles 
    ASSERT_EQ(vec, b); 

    // compiles 
    vec == deq; 

    // doesn't compile 
    ASSERT_EQ(vec, deq); 
} 

Các ASSERT_EQ(vec, deq) kết quả dòng trong thông báo sau từ Apple 6.0 kêu vang:

test/gtest.h:18861:16: error: invalid operands to binary expression ('const std::__1::vector<char, std::__1::allocator<char> >' and 'const 
     std::__1::deque<char, std::__1::allocator<char> >') 
    if (expected == actual) { 
     ~~~~~~~~^~~~~~~ 
../x86_64-linux_debian-7/tests/gtest/gtest.h:18897:12: note: in instantiation of function template specialization 'testing::internal::CmpHelperEQ<std::__1::vector<char, 
     std::__1::allocator<char> >, std::__1::deque<char, std::__1::allocator<char> > >' requested here 
    return CmpHelperEQ(expected_expression, actual_expression, expected, 
     ^
tst.cc:27:5: note: in instantiation of function template specialization 'testing::internal::EqHelper<false>::Compare<std::__1::vector<char, std::__1::allocator<char> >, 
     std::__1::deque<char, std::__1::allocator<char> > >' requested here 
     ASSERT_EQ(vec, deq); 
     ^

khi gcc 4.7.2 liệt kê tất cả các mẫu nó đã cố gắng và thất bại trong việc thực hiện expected == actual công việc, bỏ qua cái tôi đã cung cấp.

Những gì tôi không hiểu là tại sao

  • ASSERT_EQ(vec, b) tìm được cung cấp operator ==; và
  • vec == deq biên dịch; nhưng
  • ASSERT_EQ(vec, deq) thì không.

Ai đó có thể làm sáng tỏ điều này? Nó phải là một cái gì đó rất rõ ràng, nhưng tôi không thể nhìn thấy nó.

Trả lời

0

Câu trả lời ngắn:

Thất bại trong việc tìm ra đúng operator== mẫu chủ yếu là do thực tế rằng Google thử nghiệm định nghĩa riêng của nó operator== mẫu và tra cứu không gian tên quy tắc không sử dụng ADL chọn mẫu đó và từ chối nó. ADL, như được chỉ ra bởi Amadeus, không thể hy vọng tìm được mẫu mà tôi đã định nghĩa.

Giải pháp:

Như Amadeus chỉ ra, di chuyển mọi thứ vào không gian tên std (trong trường hợp này để có được ADL làm việc) không được khuyến khích.

Tôi không có gì phải lo ngại về việc làm ô nhiễm không gian tên của Google Test, vì vậy hãy di chuyển mẫu của tôi vào ::testing::internals giải quyết vấn đề (sử dụng tra cứu thông thường, chứ không phải ADL).

Câu trả lời dài hơn:

kỳ vọng của tôi là toàn cầu operator== nên được khám phá qua những gì Vandevoorde & Josuttis, C++ Templates Phần 9.2, p.122, hãy gọi số tra cứu thông thường.

Dưới đây là mã minh họa này:

#include <vector> 
#include <deque> 

template< typename T> 
bool operator==( const std::vector<T>& v , const std::deque<T>& d); 

namespace A { 

    template <typename T1, typename T2> 
    bool EQ(const T1& expected, const T2& actual) { 
     return expected == actual; 
    } 
} 

void TestBody() { 

    std::vector<char> vec; 
    std::deque<char> deq; 

    ::A::EQ(vec, deq) ; 
} 

biên dịch thành công này. Tôi đọc câu trả lời của Amadeus là Amadeus tin rằng điều đó sẽ thất bại do ADL. Tuy nhiên, trong trường hợp này ADL là không phải được sử dụng để tìm operator==. Điều này có thể được chứng minh bằng một cách rõ ràng tắt ADL trong cuộc gọi đến các nhà điều hành bằng cách viết lại

expected == actual 

như

return (operator==)(expected, actual); 

V&J Mục 9.2.1, p.123:

ADL là cũng bị ức chế nếu tên của hàm được gọi là được đặt trong dấu ngoặc đơn

trong trường hợp mã vẫn biên dịch.

Để xác định tại sao đoạn code liên quan đến Google thử nghiệm thất bại, tôi đã thực hiện phẫu thuật thay vì cực đoan trên các tiêu đề Google thử nghiệm cho đến khi tôi được chiết xuất chỉ mã gây ra lỗi biên dịch, dẫn đến một định nghĩa của operator== trong không gian tên testing::internal trong gtest/internal/gtest-linked_ptr.h :

namespace testing { 
namespace internal { 
[...] 
template<typename T> inline 
bool operator==(T* ptr, const linked_ptr<T>& x) { 
    return ptr == x.get(); 
} 
[...] 
} 
} 

dịch đó vào kết quả mã kiểm tra của tôi trong:

#include <vector> 
#include <deque> 

template< typename T> 
bool operator==( const std::vector<T>& v , const std::deque<T>& d); 

namespace A { 

    struct S {}; 
    template<typename T> bool operator==(T* ptr, S& x); 

    template <typename T1, typename T2> 
    bool EQ(const T1& expected, const T2& actual) { 
     return expected == actual; 
    } 
} 

void TestBody() { 

    std::vector<char> vec; 
    std::deque<char> deq; 

    ::A::EQ(vec, deq) ; 
} 

này thành công thất bại trong việc biên dịch với các mẫu lỗi unfound. Sở thích là thông báo lỗi đầu tiên:

gtst.cc: In instantiation of ‘bool A::EQ(const T1&, const T2&) [with T1 = std::vector<char>; T2 = std::deque<char>]’: 
gtst.cc:25:21: required from here 
gtst.cc:14:37: error: no matching function for call to ‘operator==(const std::vector<char>&, const std::deque<char>&)’ 
gtst.cc:14:37: note: candidates are: 
gtst.cc:10:31: note: template<class T> bool A::operator==(T*, A::S&) 
gtst.cc:10:31: note: template argument deduction/substitution failed: 
gtst.cc:14:37: note: mismatched types ‘T*’ and ‘std::vector<char>’ 

Vì vậy, trước tiên, hãy xem A::operator==.

Stroustrup, The C++ Programming Language, 4th Edition, Mục 26.3.5 tr. 753 quốc gia mà các ràng buộc của tên phụ thuộc được thực hiện bằng cách nhìn vào

  1. Tên trong phạm vi tại điểm mà mẫu được định nghĩa, cộng với
  2. tên trong không gian tên của một cuộc tranh cãi của một cuộc gọi phụ thuộc

Trong trường hợp này, theo quy tắc đầu tiên, A::operator== phải được chọn thay vì ::operator==. ADL cũng không tìm thấy ::operator== bởi vì, như Amadeus chỉ ra, nó không có trong không gian tên std.

Để thuyết phục bản thân rằng lỗi biên dịch thực sự là kết quả của quy tắc đầu tiên, tôi đã di chuyển định nghĩa ::operator== vào không gian tên A và tắt ADL như trước.

Mã biên dịch thành công.

4

Vấn đề của bạn là do ADL (tra cứu phụ thuộc đối số). std::vectorstd::deque, như bạn đã biết, được xác định trong không gian tên std, nhưng bạn đang xác định operator== tại không gian tên chung và ADL không tìm được hàm này.

Để giải quyết vấn đề của bạn, bạn phải xác định operator== trong cùng một không gian tên của vùng chứa của bạn, đó là bên trong không gian tên std. Vấn đề là bạn đang KHÔNG ĐƯỢC PHÉP để làm điều đó. Bằng cách này, tôi sẽ đề nghị bạn thay đổi một chút cách tiếp cận của bạn. Tại sao không thử một cái gì đó như thế:

template< typename T> 
bool equal(const std::vector<T>& v , const std::deque<T>& d) { return false; } 

TEST(A, B) { 
    std::vector<char> vec; 
    std::deque<char> deq; 
    ASSERT_TRUE(equal(vec, deq)); 
} 
+0

Nếu trường hợp này xảy ra, không nên 'ASSERT_EQ (vec, b)' cũng không thành công? –

+0

Lưu ý rằng 'struct bar' được định nghĩa tại cùng một không gian tên trong đó' toán tử == 'được định nghĩa quá.Điều đó có nghĩa là khi trình biên dịch thấy 'ASSERT_EQ (vec, b)', nó sẽ cố gắng tìm 'operator ==' trong không gian tên std, do 'vec', trong không gian tên chung, do' b' và trong thử nghiệm :: namespace nội bộ , do gtest. Nó sẽ tìm và biên dịch – Amadeus

+0

Mặt khác, 'ASSERT_EQ (vec, deq)' có các đối số của nó được định nghĩa trong không gian tên std, do đó, 'operator ==' không phải là một ứng cử viên. Bạn có thể xác minh yourselt bằng cách định nghĩa 'operator ==' như: 'namespace std {template < typename T> toán tử bool == (const std :: vector & v, const std :: deque & d) {return false; }} '. Nhưng, một lần nữa, điều này là ** KHÔNG ** cho phép bởi các tiêu chuẩn C++. Bạn có thể chuyên, nhưng bạn không thể quá tải – Amadeus

Các vấn đề liên quan