मैं एक टेम्पलेटेड मित्र कार्य करना चाहता हूं। हालांकि, मुझे नहीं पता कि इसे बिना किसी टेम्पलेट फ़ंक्शन के उसी तरह कैसे काम करना है। यहाँ एक नमूना कोड है

#include <iostream>

namespace ns{
struct Obj {
    friend void foo(Obj){std::cout << "no problem" << std::endl;}

    template<typename T>
    friend void bar(Obj){std::cout << "problem" << std::endl;}
};
}

int main() {
    ns::Obj obj;
    foo(obj); // Compile
    bar<int>(obj); // Not compile
    return 0;
}
4
Antoine Morrier 9 मई 2018, 23:22

2 जवाब

सबसे बढ़िया उत्तर

C++20 से पहले, आपको कंपाइलर को यह सिखाने की जरूरत है कि bar एक टेम्प्लेट का नाम है ताकि यह जान सके कि < एक टेम्प्लेट तर्क सूची शुरू करता है और यह ऑपरेटर से कम नहीं है:

template<char> void bar() = delete;

int main() {
    ns::Obj obj;
    foo(obj); // Compile
    bar<int>(obj); // Now compiles too
    return 0;
}

ध्यान दें कि सभी bar ओवरलोड को एक फ़ंक्शन टेम्प्लेट होना करना है। हस्ताक्षर तब तक मायने नहीं रखता जब तक कि यह इतना अच्छा न हो कि अधिभार समाधान में हस्तक्षेप कर सके; () एक अच्छा विकल्प है क्योंकि परिभाषा के अनुसार हम कम से कम एक तर्क पारित कर रहे हैं, इसलिए कोई पैरामीटर नहीं लेने वाला फ़ंक्शन टेम्पलेट कभी भी व्यवहार्य नहीं हो सकता है।

वैकल्पिक रूप से, आप एक टैग तर्क से T निकालने के लिए bar को फिर से डिज़ाइन कर सकते हैं:

template<class T>
struct type {};

namespace ns{
struct Obj {    
    // ...

    template<typename T>
    friend void bar(Obj, type<T>) { /* ... */ }
};
}
// ...

bar(obj, type<int>()); // OK

C++20 में, कंपाइलर यह मान लेगा कि bar एक टेम्प्लेट को नाम देता है जब वह < देखता है और नाम लुकअप कुछ भी नहीं पाता है, इसलिए आपका कोड बस काम करेगा

8
T.C. 9 मई 2018, 23:42

सीधा तरीका यह होगा कि आगे की घोषणा को जोड़ा जाए और योग्य लुकअप का उपयोग करके फ़ंक्शन को स्थित होने दिया जाए:

namespace ns{
struct Obj;

void foo(Obj);

template<typename T>
void bar(Obj);

struct Obj {
    friend void foo(Obj){std::cout << "no problem" << std::endl;}

    template<typename T>
    friend void bar(Obj){std::cout << "problem " << std::endl;}
};
} // namespace ns

int main() {
    ns::Obj obj;
    ns::foo(obj); // Ok
    ns::bar<int>(obj); // Ok
    return 0;
}
4
user7860670 9 मई 2018, 23:54