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:
- Invoke
pPrint
- Invoke
toString
- Simply output NO print Function
My main function:
int main() {
LD ld = { "And", "Ap" };
UP up = { "James Brannd", "jamens@goo.com" };
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:
- Prioriy (mentioned earlier)
- Case sensitive same function
- Const type distinguish function should be
pPrint
only and const too. - You cant what's inside any of the struct and main function that is template class should be seperate and independent.
- Only C++11 standards
The class should work for this two prototype only:
ostream& pPrint(ostream& ost) const // case sentive for pPrint
std::string toString() const
References: