gpt4 book ai didi

c++ - 模板类根据它们的存在和优先级调用其他类的一些命名函数

转载 作者:行者123 更新时间:2023-11-30 02:27:39 26 4
gpt4 key购买 nike

我有这样的结构/类:

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 函数。如果没有,它将调用该类的 toString 函数,如果它也不可用,它将打印“NO print function”

优先级:-1)p打印2)到字符串3)简单输出“NO print Function”

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)if not this to "No func available"

p应检测到具有此原型(prototype)的打印:

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 来做到这一点?

最佳答案

我认为解决这个问题的更好方法是通过在 C++17 中被标准化为 std::is_detected 的检测习惯用法。

C++11

首先我们需要一些辅助结构和类型别名来实现检测习惯用法:

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;

然后我们简化标签分发调用:

 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";
}

Live Demo

我们的测试:

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;

输出:

Name: James Brannd Email: jamens@goo.com
Username: And Password: Ap
NO print Function

(事实上,我可能会将所有 CallPrint 方法隐藏为 private 因为我不希望用户调用它们,但我保留了现有的方法原样,因为这就是 OP 拥有它们的方式)


C++17

我们的检测习语将使用std::is_detectedconstexpr if

Demo

(我不认为编译器支持 [[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";
}
}
}

关于c++ - 模板类根据它们的存在和优先级调用其他类的一些命名函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41488450/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com