我有这样的结构/类:
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";
}
};
我正在创建一个模板pPrint类,如果它存在,它将调用该类的pPrint函数。如果没有,它将调用该类的String函数,如果它也不可用它将打印“NO print function”
优先权: - 1)pPrint 2)的toString 3)只输出“无打印功能”
int main() {
LD ld = { "And", "Ap" };
UP up = { "James Brannd", "jamens@goo.com" };
// this should print "Name: James Email: jamens@goo.com"
std::cout << PPrint <UP> (up) << std::endl;
// this should print "Username: And Password: Ap"
std::cout << PPrint <LD> (ld) << std::endl;
}
现在我创建了这个类,如下所示:
template<typename T>
struct HaspPrintMethod
{
template<typename U, std::ostream&(U::*)(std::ostream&) const> struct SFINAE {};
template<typename U> static char Test(SFINAE<U, &U::pPrint>*);
template<typename U> static int Test(...);
static const bool Has = sizeof(Test<T>(0)) == sizeof(char);
};
template <class T>
class PPrint {
public:
PPrint(T m)
{
CallPrint(m, std::integral_constant<bool, HaspPrintMethod<T>::Has>());
}
void CallPrint(const T& m, std::true_type)
{
std::ostringstream os;
m.pPrint(os);
buf = os.str();
}
void CallPrint(const T& m, std::false_type)
{
buf = m.toString();
}
std::string buf;
};
template <class T>
std::ostream& operator<<(std::ostream &os, pPrint<T> const &m)
{
return os << m.buf;
}
但它不起作用 参考:Check if a class has a member function of a given signature
新要求: - 模板类名称为PPrint 我们想要检测的功能是 1)pPrint 2)toString 3)如果不是“No func available”
应检测使用此原型的pPrint:
ostream& pPrint(ostream& ost) const;
但结构中的函数可以是:(不应该被检测到)
ostream& PPrint(ostream& ost) const; // case sensitive and same name as class name
ostream& pPrint(ostream& ost); //without const specifier
如何构建模板类PPrint呢?
答案 0 :(得分:2)
我认为更好的方法是通过在C ++ 17中标准化为std::is_detected
的检测习惯用法。首先,我们需要一些辅助结构和类型别名来实现检测习惯用法:
template<class...>
using void_t = void;
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;
并检查toString
:
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;
然后我们简化了tag-dispatch调用:
pPrint(T m)
{
CallPrint(m, HaspPrintMethod_t<T>());
}
如果没有pPrint
方法可用,我们会输入std::false_type
标记,然后我们会进一步发送:
void CallPrint(const T& m, std::false_type)
{
CallPrintNopPrint(m, HasToStringMethod_t<T>());
}
private:
void CallPrintNopPrint(const T& m, std::true_type)
{
buf = m.toString();
}
void CallPrintNopPrint(const T& m, std::false_type)
{
buf = "NO print Function";
}
我们的测试:
LD ld = { "And", "Ap" };
UP up = { "James Brannd", "jamens@goo.com" };
// this should print "Name: James Email: jamens@goo.com"
std::cout << pPrint <UP> (up) << std::endl;
// this should print "Username: And Password: Ap"
std::cout << pPrint <LD> (ld) << std::endl;
// this should print "NO print Function";
struct Foo{};
Foo f;
std::cout << pPrint<Foo>(f) << std::endl;
输出:
姓名:James Brannd电邮:jamens@goo.com
用户名:和密码:Ap
没有打印功能
(事实上,我可能会将所有CallPrint
方法隐藏为private
因为我不希望用户给他们打电话,但我将现有的方法留作了 - 是因为那是OP如何拥有它们)
我们的检测惯用法将使用std::is_detected和constexpr if
(我不认为编译器支持[[maybe_unused]]
attribute specifier,否则我会使用它并压制警告)
template<class T>
using HasPrintMethod = decltype(std::declval<T>().pPrint(std::declval<std::ostream&>()));
template<class T>
using HasToStringMethod = decltype(std::declval<T>().toString());
// ...
constexpr pPrint(T m)
{
if constexpr(is_detected<HasPrintMethod, T>::value)
{
std::ostringstream os;
m.pPrint(os);
buf = os.str();
}
else
{
if constexpr (is_detected<HasToStringMethod, T>::value)
{
buf = m.toString();
}
else
{
buf = "NO print Function";
}
}
}
答案 1 :(得分:1)
你可以使用另一个integral_constant来获得你想要的优先级
<TAG1 Attribute1="1234" Attribute2="1234" Attribute3="1234">
<TAG2 xpq="123" abc="000" lkj="123"/>
</TAG1>