我有这样的结构/类:
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;
}
};
我正在创建一个模板PPrint
类,如果它存在,它将调用该类的pPrint
函数。如果没有,它将调用该类的toString
函数,如果它也不可用,它将打印 NO print function 。
优先级:
pPrint
toString
我的主要职能:
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;
}
现在我创建了这个类,如下所示:
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";
}
};
它不正确,因为它不能区分const及其给出的错误,如下所示我的编译器,但在其他人上运行并打印H
的功能(它必须不打印):
error: ‘struct UP’ has no member named ‘PPrint’
m.PrettyPrint(os);
但它在意识形态和Coliru上运行良好。
我应该如何创建此类或删除此类错误? 主要挑战是:
pPrint
和const也是。该课程仅适用于这两个原型:
ostream& pPrint(ostream& ost) const // case sentive for pPrint
std::string toString() const
参考文献:
答案 0 :(得分:1)
您可以使用类似的方法来减少解决方案的样板并解决问题:
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);
}
重载,继承和sfinae将完成这项工作。
基于问题代码的最小工作示例:
#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", "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;
}