admin管理员组文章数量:1389960
I have a template friend function named print
.
Is there a way to overload print
for specific types of contexts (the first parameter)
- such that the overload is also a friend and
- without forward declaring these contexts in
clause.h
?
Here are definitions for the class and friend function:
#include <iostream>
struct clause;
template <typename Context>
void print(const Context &, const clause &c);
struct clause {
private:
template <typename Context>
friend void print(const Context &, const clause &c);
int i = 8;
};
template <typename Context>
void print(const Context &, const clause &c) {
std::cerr << c.i << " friend\n";
}
I would like to do something like this:
#include "clause.h"
class special_context {};
// Fails as this is an overload, not a specialization.
void print(const special_context &, const clause &c) {
std::cerr << c.i << " overload\n"; // not a friend
}
I have a template friend function named print
.
Is there a way to overload print
for specific types of contexts (the first parameter)
- such that the overload is also a friend and
- without forward declaring these contexts in
clause.h
?
Here are definitions for the class and friend function:
#include <iostream>
struct clause;
template <typename Context>
void print(const Context &, const clause &c);
struct clause {
private:
template <typename Context>
friend void print(const Context &, const clause &c);
int i = 8;
};
template <typename Context>
void print(const Context &, const clause &c) {
std::cerr << c.i << " friend\n";
}
I would like to do something like this:
#include "clause.h"
class special_context {};
// Fails as this is an overload, not a specialization.
void print(const special_context &, const clause &c) {
std::cerr << c.i << " overload\n"; // not a friend
}
Share
Improve this question
edited Mar 15 at 19:14
Rumburak
asked Mar 15 at 18:27
RumburakRumburak
3,59318 silver badges28 bronze badges
7
|
Show 2 more comments
2 Answers
Reset to default 4such that the overload is also a friend and
We can't do that. We have to list overloaded functions in friends.
This can be achieved with functional objects (functors).
#include <functional>
#include <iostream>
#include <type_traits>
template <typename T>
struct clause {
private:
friend struct print;
int i = 8;
};
class special_context {};
struct print {
template <typename Context, typename T>
void operator()(const Context&, const clause<T>& c) {
std::cerr << c.i << " friend\n";
}
template <typename T>
void operator()(const special_context&, const clause<T>& c) {
std::cerr << c.i << " overload\n";
}
};
int main() {
clause<int> c;
std::invoke(print{}, nullptr, c); // or print{}(nullptr, c), or print()(nullptr, c);
std::invoke(print{}, special_context{}, c);
}
https://godbolt./z/4bqvrnar1
Further development - enclose the functional object calls into functions
#include <functional>
#include <iostream>
#include <type_traits>
template <typename T>
struct clause {
private:
friend struct printer;
int i = 8;
};
class special_context {};
struct printer {
template <typename Context, typename T>
void operator()(const Context&, const clause<T>& c) {
std::cerr << c.i << " friend\n";
}
template <typename T>
void operator()(const special_context&, const clause<T>& c) {
std::cerr << c.i << " overload\n";
}
};
template <typename Context, typename T>
void print(const Context&, const clause<T>& c) {
std::invoke(printer{}, nullptr, c);
}
template <typename T>
void print(const special_context& ctx, const clause<T>& c) {
std::invoke(printer{}, ctx, c);
}
int main() {
clause<int> c;
print(nullptr, c);
print(special_context{}, c);
}
https://godbolt./z/Tb73n1nan
Expanding on 3CxEZiVlQ
's answer, using a template class printer
does the trick neatly:
This is clause
with the default print function, which is implemented in the friend class printer
:
// clause.h
#include <iostream>
struct clause {
private:
template <typename Context>
friend struct printer;
int i = 8;
};
template <typename Context>
struct printer {
void print(const Context&, const clause& c) {
std::cerr << c.i << " friend\n";
}
};
template <typename Context>
void print(const Context& context, const clause& clause) {
printer<Context>{}.print(context, clause);
}
And then we can specialize the printer:
#include "clause.h"
class special_context {};
template <>
struct printer<special_context> {
void print(const special_context&, const clause& c) {
std::cerr << c.i << " overload\n";
}
};
int main() {
clause c;
print(nullptr, c);
print(special_context{}, c);
}
See https://godbolt./z/zbr3qTn6a
本文标签: cOverloading template friend functionStack Overflow
版权声明:本文标题:c++ - Overloading template friend function - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744606378a2615380.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
struct clause
and a pair of (non-template) function overloads,void print(const generic_context &, const clause &)
andvoid print(const special_context &, const clause &)
. Is there a way to declare both overloads asfriend
without forward declaringspecial_context
? – JaMiT Commented Mar 15 at 18:42clause
to be a template, but does your question needclause
to be a template? If you got an answer whereclause
is not a template, would you not be able to adapt that answer to your real code? If you can simplify your question by thinking more abstractly, there is a better chance that the question will be applicable to more people in the future. – JaMiT Commented Mar 15 at 18:54