2016-08-20 10 views
10

नहीं मिल सकता है मैं गूगल टेस्ट v1.7Google परीक्षा उपयोगकर्ता प्रदान की समानता ऑपरेटर

मैं एक कस्टम operator == जो ASSERT_EQ नहीं मिल रहा है बना लिया है का उपयोग कर रहा है, लेकिन जो करता है, तो सीधे इस्तेमाल किया पाया जा सकता है। यहाँ कोड

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

है से एप्पल 6.0 बजना निम्न संदेश में ASSERT_EQ(vec, deq) लाइन परिणाम:

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); 
     ^

जबकि जीसीसी 4.7.2 सूचियों टेम्पलेट्स इसे करने की कोशिश और expected == actual काम करने में विफल के सभी, अनदेखी मैंने प्रदान किया।

क्या मुझे समझ नहीं आता क्यों

  • ASSERT_EQ(vec, b) प्रदान की operator == पाता है; और
  • vec == deq संकलन; लेकिन
  • ASSERT_EQ(vec, deq) नहीं है।

क्या कोई इस पर कुछ प्रकाश डाल सकता है? यह कुछ स्पष्ट रूप से स्पष्ट होना है, लेकिन मैं इसे नहीं देख सकता।

उत्तर

0

संक्षिप्त उत्तर:

सही operator== टेम्पलेट को खोजने के लिए विफलता मुख्य रूप से सच है कि गूगल टेस्ट को परिभाषित करता है कि यह खुद है की वजह से है operator== टेम्पलेट और नाम स्थान देखने नियम जो एडीएल का उपयोग नहीं करता है वह टेम्पलेट चुनता है और इसे अस्वीकार करता है। एडीएल, जैसा कि अमेडियस द्वारा इंगित किया गया है, मैं जिस टेम्पलेट को परिभाषित करता हूं उसे ढूंढने की उम्मीद नहीं कर सकता।

समाधान:

एमॅड्यूस बताते हैं के रूप में, std नेम स्पेस में बातें चलती (इस मामले में ADL काम करने के लिए प्राप्त करने के लिए) हतोत्साहित किया जाता है।

मेरे पास Google टेस्ट के नामस्थान को प्रदूषित करने के बारे में कोई योग्यता नहीं है, इसलिए मेरा टेम्पलेट ::testing::internals में ले जाने से समस्या हल हो जाती है (सामान्य लुकअप का उपयोग करके, एडीएल नहीं)।

लंबा उत्तर:

मेरे उम्मीद है कि वैश्विक operator== क्या Vandevoorde & Josuttis, C++ Templates धारा 9.2, पी के माध्यम से की खोज की जानी चाहिए थी।122, शब्द साधारण लुकअप

यहाँ कोड इस illustrating है:

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

यह सफलतापूर्वक संकलित करता है। अमेडियस के जवाब का मेरा पठन यह है कि अमेडियस का मानना ​​है कि एडीएल के कारण असफल होना चाहिए। हालांकि, इस मामले में एडीएल operator== खोजने के लिए उपयोग किया जाता है।

ADL है: यह पुनर्लेखन

expected == actual 

रूप

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

V&J धारा 9.2.1, पृष्ठ 123 से स्पष्ट रूप से ऑपरेटर के लिए कॉल में ADL को बंद करके प्रदर्शन किया जा सकता फ़ंक्शन का नाम ब्रांड्स में संलग्न होता है यदि

किस मामले में कोड अभी भी संकलित करता है।

आदेश क्यों Google परीक्षा से जुड़े कोड में विफल रहा है निर्धारित करने के लिए, मैं नहीं बल्कि चरम सर्जरी Google परीक्षा हेडर पर जब तक मैं संकलक त्रुटियों के कारण बस कोड निकाला है, जो gtest/internal/gtest-linked_ptr.h में testing::internal नाम स्थान में operator== की एक परिभाषा के लिए नेतृत्व किया प्रदर्शन :

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

में अपने परीक्षण कोड परिणामों में अनुवाद कर रहा है कि:

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

यह सफलतापूर्वक unfound टेम्पलेट त्रुटियों के साथ संकलित करने के लिए विफल रहता है।

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>’ 

तो, यह पहली बार A::operator== में दिख रही है: ब्याज की विफलता का पहला संदेश है।

Stroustrup, The C++ Programming Language, 4th Edition, धारा 26.3.5 पी। 753 कहा गया है कि निर्भर नामों में से बाध्यकारी एक आश्रित कॉल की एक बहस के नाम स्थान में बिंदु जहां टेम्पलेट परिभाषित किया गया है पर दायरे में

  1. को देख नामों से किया जाता है, के साथ साथ
  2. नाम

इस मामले में, पहले नियम, A::operator== को ::operator== के बजाय चुना जाना चाहिए। एडीएल भी ::operator== खोजने में विफल रहता है, क्योंकि अमेडियस बताता है, यह std नामस्थान में नहीं है।

खुद को यह समझाने के लिए कि संकलन विफलता वास्तव में पहले नियम का परिणाम है, मैंने ::operator== की परिभाषा को A नामस्थान में स्थानांतरित कर दिया और पहले एडीएल बंद कर दिया।

कोड सफलतापूर्वक संकलित करता है।

4

आपकी समस्या एडीएल (तर्क निर्भर लुकअप) के कारण है। std::vector और std::deque, जैसा कि आप पहले ही जानते हैं, std नेमस्पेस में परिभाषित हैं, लेकिन आप वैश्विक नामस्थान पर operator== को परिभाषित कर रहे हैं और एडीएल इस फ़ंक्शन को ढूँढने में विफल रहा है।

अपनी समस्या को हल करने के लिए, आपको operator== को अपने कंटेनर के समान नामस्थान में परिभाषित करना होगा, जो std नामस्थान के अंदर है। समस्या यह है कि ऐसा करने के लिए की अनुमति नहीं है। इस तरह, मैं आपको सुझाव दूंगा कि आप केवल अपना दृष्टिकोण बदल दें। क्यों ऐसा ही कुछ करने की कोशिश नहीं:

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

यदि यह मामला था, तो 'ASSERT_EQ (vec, b)' भी असफल नहीं होना चाहिए? –

+0

ध्यान दें कि 'struct bar' को उसी नामस्थान पर परिभाषित किया गया है जिसमें 'ऑपरेटर ==' भी परिभाषित किया गया है।इसका अर्थ यह है कि जब संकलक 'ASSERT_EQ (vec, b) देखता है, तो' बीसी 'के कारण, वैश्विक नामस्थान में 'vec' के कारण, std नेमस्पेस में' ऑपरेटर ==' 'खोजने का प्रयास करेगा और परीक्षण में :: आंतरिक नामस्थान gtest के कारण। यह इसे मिलेगा और – Amadeus

+0

संकलित करेगा, दूसरी तरफ, 'ASSERT_EQ (vec, deq)' के पास std namespace में परिभाषित तर्क हैं, इसलिए 'ऑपरेटर == 'उम्मीदवार नहीं है। आप 'ऑपरेटर ==' को परिभाषित करके yourselt को सत्यापित कर सकते हैं: 'नेमस्पेस std {टेम्पलेट < typename T> बूल ऑपरेटर == (कॉन्स std :: वेक्टर और v, const std :: deque और डी) {वापसी झूठी; }} '। लेकिन, फिर से, यह ** नहीं ** ** सी ++ मानकों द्वारा अनुमत है। आप विशेषज्ञ हो सकते हैं, लेकिन आप – Amadeus

संबंधित मुद्दे