I have structs/classes like these:
struct LD { //Login detail
std::string username;
std::string password;
std::string toString() const {
return "Username: " + username
+ " Password: " + password;
}
};
struct UP { //User Profile
std::string name;
std::string email;
ostream& pPrint(ostream& ost) const {
ost << "Name: " << name
<< " Email: " << email;
return ost;
}
std::string toString() const {
return "NULLSTRING";
}
};
struct CD { //ContactDetails
std::string m_phoneNumber;
std::string m_address;
ostream& pPrint(ostream& ost) { //NO CONST must not print
ost << "PhoneNumber: " << m_phoneNumber << " Address:" << m_address;
return ost;
}
} ;
struct H {
std::string hobbies;
ostream& PPrint(ostream& ost) { //its not case equivalent and not const so it should not be called
ost << "Hobbies: " << m_hobbies;
return ost;
}
} ;
struct PD {
std::string cardNumber;
ostream& pPrint(ostream& ost) const {
ost << "CardNumber: " << m_cardNumber;
return ost;
}
} ;
struct BN {
std::string m_bankName;
std::string toString() const {
return "BANKNAME";
}
ostream& simplePrint(ostream& ost) const {
ost << "BankName: " << m_bankName;
return ost;
}
} ;
struct DI {
std::string toString() const {
return "i0S";
}
ostream& pPrint(ostream& ost) const {
ost << "Android: JellyBean";
return ost;
}
};
I am creating a template PPrint
class which will call pPrint
function of that class if its present. If not, it will call toString
function of that class if its also not available it will print NO print function.
Priorities:
pPrint
toString
My main function:
int main() {
LD ld = { "And", "Ap" };
UP up = { "James Brannd", "[email protected]" };
CD cd = { "+9198799911", "355 B. Bway, NY" };
H hb = { "sing, dance, read"};
PD pd = { "444411113336667732222" };
BN bn = { "SBI" };
DI di;
std::cout << PPrint <UP> (up) << std::endl;
std::cout << PPrint <LD> (ld) << std::endl;
std::cout << PPrint <CD> (cd) << std::endl;
std::cout << PPrint <H>(hb) << std::endl;
std::cout << PPrint <PD> (pd) << std::endl;
std::cout << PPrint <BN> (bn) << std::endl;
std::cout << PPrint <DI> (di) << std::endl;
}
Now I have created this class as below:
template<class...>
using void_t = void;
// pPrint
template<typename T, typename = void_t<>>
struct HaspPrintMethod : std::false_type{};
template<typename T>
struct HaspPrintMethod<T, void_t<decltype(std::declval<T> ().pPrint(std::declval<std::ostream&>()))>> : std::true_type{};
// PPrint
template<typename T, typename = void_t<>>
struct HasPPrintMethod : std::false_type{};
template<typename T>
struct HasPPrintMethod<T, void_t<decltype(std::declval<T>().PPrint(std::declval<std::ostream&>()))>> : std::true_type{};
template<typename T>
using HasPPrintMethod_t = typename HasPPrintMethod<T>::type;
// both pPrint and PPrint
template<typename T>
struct HasAnyPPrintMethod : std::integral_constant<bool, HasPPrintMethod<T>::value || HaspPrintMethod<T>::value>{};
template<typename T>
using HasAnyPPrintMethod_t = typename HasAnyPPrintMethod<T>::type;
template<typename T, typename=void_t<>>
struct HastoStringMethod : std::false_type{};
template<typename T>
struct HastoStringMethod<T, void_t<decltype(std::declval<T>().toString())>> : std::true_type{};
template<typename T>
using HastoStringMethod_t = typename HastoStringMethod<T>::type;
template <class T>
class PPrint {
public:
PrettyPrint(T m)
{
CallPrint(m, HasAnyPPrintMethod_t<T>());
}
std::string buf;
private:
void CallPrint( T& m, std::true_type)
{
CallPPrint(m, HasPPrintMethod_t<T>());
}
void CallPPrint(T& m, std::true_type)
{
std::ostringstream os;
m.PPrint(os); //need correction as pPrint is only priority for THis "NO print function" if pPrint is nor there and toString is not there I mean it should ignored
buf = os.str();
}
void CallPrettyPrint(T& m, std::false_type)
{
std::ostringstream os;
m.pPrint(os); //only i want this one as 1st priority PPrint must be not used anywhere , should not be printed
buf = os.str();
}
void CallPrint( T& m, std::false_type)
{
CallPrintNoPPrint(m, HastoStringMethod_t<T>());
}
void CallPrintNoPPrint( T& m, std::true_type)
{
buf = m.toString();
}
void CallPrintNoPrettyPrint( T& m, std::false_type)
{
buf = "NO print Function";
}
};
It's not correct because it's not distinguishing for const and its giving error like below for my compiler but running on others and printing H
's function (which it must not print):
error: ‘struct UP’ has no member named ‘PPrint’
m.PrettyPrint(os);
But it's running fine on ideone and Coliru.
How should I create such class or remove such errors?
Main challenges are:
pPrint
only and const too.The class should work for this two prototype only:
ostream& pPrint(ostream& ost) const // case sentive for pPrint
std::string toString() const
References:
You can use something like this to reduce the boilerplate of your solution and solve the issue:
struct SimplyOutput {};
struct ToString: SimplyOutput {};
struct PPrint: ToString {};
template<typename T>
void pPrintImpl(SimplyOutput, const T &) {
// Do whatever you want here
}
template<typename T>
auto pPrintImpl(ToString, const T &t)
-> decltype(t.toString()) {
// Do whatever you want here
}
template<typename T>
auto pPrintImpl(PPrint, const T &t)
-> decltype(t.pPrint(std::declval<std::ostream>())) {
// Do whatever you want here
}
template<typename T>
auto pPrint(const T &t)
-> decltype(pPrintImpl(PPrint{}, t)) {
return pPrintImpl(PPrint{}, t);
}
Overloading, inheritance and sfinae will do the job.
Below a minimal, working example based on the code in the question:
#include<iostream>
#include<string>
#include<sstream>
struct LD { //Login detail
std::string username;
std::string password;
std::string toString() const {
return "Username: " + username
+ " Password: " + password;
}
};
struct UP { //User Profile
std::string name;
std::string email;
std::ostream& pPrint(std::ostream& ost) const {
ost << "Name: " << name
<< " Email: " << email;
return ost;
}
std::string toString() const {
return "NULLSTRING";
}
};
struct CD { //ContactDetails
std::string m_phoneNumber;
std::string m_address;
std::ostream& pPrint(std::ostream& ost) { //NO CONST must not print
ost << "PhoneNumber: " << m_phoneNumber << " Address:" << m_address;
return ost;
}
} ;
struct H {
std::string m_hobbies;
std::ostream& PPrint(std::ostream& ost) { //its not case equivalent and not const so it should not be called
ost << "Hobbies: " << m_hobbies;
return ost;
}
} ;
struct PD {
std::string m_cardNumber;
std::ostream& pPrint(std::ostream& ost) const {
ost << "CardNumber: " << m_cardNumber;
return ost;
}
} ;
struct BN {
std::string m_bankName;
std::string toString() const {
return "BANKNAME";
}
std::ostream& simplePrint(std::ostream& ost) const {
ost << "BankName: " << m_bankName;
return ost;
}
} ;
struct DI {
std::string toString() const {
return "i0S";
}
std::ostream& pPrint(std::ostream& ost) const {
ost << "Android: JellyBean";
return ost;
}
};
template<typename T>
class PPrint {
struct SimplyOutputTag {};
struct ToStringTag: SimplyOutputTag {};
struct PPrintTag: ToStringTag {};
template<typename U = T>
void internal(SimplyOutputTag, const U &) {
buf = "NO print Function";
}
template<typename U = T>
auto internal(ToStringTag, const U &u)
-> decltype(u.toString(), void()) {
buf = u.toString();
}
template<typename U = T>
auto internal(PPrintTag, const U &u)
-> decltype(u.pPrint(std::declval<std::ostringstream &>()), void()) {
std::ostringstream os;
u.pPrint(os);
buf = os.str();
}
public:
PPrint(const T &t) {
internal(PPrintTag{}, t);
}
std::string get() const { return buf; }
private:
std::string buf;
};
template<typename T>
std::ostream & operator << (std::ostream &os, const PPrint<T> &pp) {
os << pp.get();
return os;
}
int main() {
LD ld = { "And", "Ap" };
UP up = { "James Brannd", "[email protected]" };
CD cd = { "+9198799911", "355 B. Bway, NY" };
H hb = { "sing, dance, read"};
PD pd = { "444411113336667732222" };
BN bn = { "SBI" };
DI di;
std::cout << PPrint <UP> (up) << std::endl;
std::cout << PPrint <LD> (ld) << std::endl;
std::cout << PPrint <CD> (cd) << std::endl;
std::cout << PPrint <H>(hb) << std::endl;
std::cout << PPrint <PD> (pd) << std::endl;
std::cout << PPrint <BN> (bn) << std::endl;
std::cout << PPrint <DI> (di) << std::endl;
}
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments