gpt4 book ai didi

C++11 在基类的模板参数包上调用成员函数(如果存在)

转载 作者:行者123 更新时间:2023-11-30 01:51:26 25 4
gpt4 key购买 nike

我检查了类似的问题。这很接近,但不是重复的。

本质上,如果存在的话,我想在基类的参数包上调用一个函数。我有一种 C++11 方法可以做到这一点,但我并不满意。

有人可以提供更好的[即更好的性能和更少的样板代码]:

源代码:

#include <iostream>
#include <type_traits>

using namespace std;

// a class initialised with an int that can't do it
struct A
{
A(int a) : _a(a) { }
void report() const { std::cout << _a << std::endl; }
private:
int _a;
};

// a class initialised with a string that can do it
struct B
{
B(std::string s) : _b (move(s)) { }
void report() const { std::cout << _b << std::endl; }
void do_it() { std::cout << "B did it with " << _b <<"!" << std::endl; }
private:
string _b;
};

// a class initialised with an int that can do it
struct D
{
D(int d) : _d(d) { }
void report() const { std::cout << _d << std::endl; }
void do_it() { std::cout << "D did it with " << _d <<"!" << std::endl; }
private:
int _d;
};

// a class initialised with a string that can't do it
struct E
{
E(std::string s) : _e(move(s)) { }
void report() const { std::cout << _e << std::endl; }
private:
string _e;
};

// a function enabled only if T::do_it is a member function pointer
// the bool is there just to make this function more attractive to the compiler
// than the next one, below
template<class T>
auto do_it(T& t, bool)
-> typename std::enable_if<std::is_member_function_pointer<decltype(&T::do_it)>::value, void>::type
{
t.do_it();
}

// a catch-all function called when do_it<T> is not valid
// the ... is less attractive to the compiler when do_it<T>(T&, bool) is available
template<class T>
void do_it(T& t, ...)
{
}

// a compound class derived from any number of classes - I am so lazy I work hard at
// being lazy.
template<class...Templates>
struct C : public Templates...
{
// construct from a parameter pack of arbitrary arguments
// constructing each base class with one argument from the pack
template<class...Args>
C(Args&&...args)
: Templates(std::forward<Args>(args))...
{

}

// private implementation of the dispatch mechanism here...
private:
// this will call ::do_it<T>(T&, bool) if T::do_it is a member function of T, otherwise
// calls ::do_it<T>(T&, ...)
template<class T>
void may_do_it()
{
::do_it(static_cast<T&>(*this), true);
}

// calls may_do_it for the last class in the parameter pack
template<typename T1>
void multi_may_do_it()
{
may_do_it<T1>();
}

// general case for calling do_it on a parameter pack of base classes
template<typename T1, typename T2, typename...Rest>
void multi_may_do_it()
{
may_do_it<T1>();
multi_may_do_it<T2, Rest...>();
}

// calls may_do_it for the last class in the parameter pack
template<typename T1>
void multi_report() const
{
static_cast<const T1&>(*this).report();
}

// general case for calling do_it on a parameter pack of base classes
template<typename T1, typename T2, typename...Rest>
void multi_report() const
{
static_cast<const T1&>(*this).report();
multi_report<T2, Rest...>();
}


// the functions we actually wish to expose here...
public:
// disptach T::do_it for each valid T in base class list
void do_it() {
multi_may_do_it<Templates...>();
}

// dispatch T::report, which must exist for each base class
void report() const {
cout << "-- all base classes reporting:" << endl;
multi_report<Templates...>();
cout << "-- all base classes reported" << endl;
}
};

int main()
{
C<A,B, D, E> c(10, "hello", 7, "goodbye");
c.report(); // all base classes must report
c.do_it(); // all base classes that can do_it, must.

return 0;
}

输出:

Compiling the source code....
$g++ -std=c++11 main.cpp -o demo -lm -pthread -lgmpxx -lgmp -lreadline 2>&1

Executing the program....
$demo
-- all base classes reporting:
10
hello
7
goodbye
-- all base classes reported
B did it with hello!
D did it with 7!

最佳答案

我认为这是尽可能没有样板文件的。

// a function enabled only if T::do_it is a member function pointer
template<class T>
auto do_it(T* t)
-> typename std::enable_if<std::is_member_function_pointer<decltype(&T::do_it)>::value, void>::type
{
t->do_it();
}

// a catch-all function called when do_it<T> is not valid
// the const void * is less attractive to the compiler when do_it<T>(T*) is available
template<class T>
void do_it(const void *)
{
}

// a compound class derived from any number of classes - I am so lazy I work hard at
// being lazy.
template<class...Templates>
struct C : public Templates...
{
//constructor omitted
private:
using expander = int[];
public:
// disptach T::do_it for each valid T in base class list
void do_it() {
(void) expander{ 0, (::do_it<Templates>(this), 0)...};
}

// dispatch T::report, which must exist for each base class
void report() const {
cout << "-- all base classes reporting:" << endl;
(void) expander{ 0, (Templates::report(), 0)...};
cout << "-- all base classes reported" << endl;
}
};

Demo .

关于C++11 在基类的模板参数包上调用成员函数(如果存在),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26142402/

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