[英]variadic templates with template function names and passing arguments and return values around
following from this question, I have been trying to create a template function that calls all same-named methods of its mixins. 在这个问题之后,我一直在尝试创建一个模板函数,该函数调用其mixin的所有同名方法。 This has been done and verified in the previous question.
这已在前一个问题中完成并得到验证。
Now I am attempting to get the return value of SensorType:: 现在我试图获取SensorType ::的返回值
Analytically: 分析:
#include<iostream>
#include <string>
struct EdgeSensor
{
void update(int i) { std::cout << "EdgeSensor::update " << i << std::endl; }
void updat2(const int i ) { std::cout << "EdgeSensor::updat2" << i << std::endl; }
std::string printStats() { std::cout << "EdgeSensor::printStats" << std::endl;
return std::string("EdgeSensor::printStats"); }
};
struct TrendSensor
{
void update(int i ) { std::cout << "TrendSensor::update" << i << std::endl; }
void updat2(const int i ) { std::cout << "TrendSensor::updat2" << i << std::endl; }
std::string printStats() { std::cout << "TrendSensor::printStats" << std::endl;
return std::string("TrendSensor::printStats"); }
};
template <class T, void (T::*)(const int)>
struct Method { };
template<typename ... SensorType>
class BaseSensor : public SensorType ... //to my BaseSensor class
{
template <class T, void(T::*M)(const int)>
int runSingle(Method<T, M> , const int i) {
(this->*M)(i);
return 0;
}
template <class... Ts>
void runAll(const int i) {
int run[sizeof...(Ts)] = { runSingle(Ts{},i)... };
(void)run;
}
public:
void update() {
runAll<Method<SensorType, &SensorType::update>...>(2);
}
void updat2() {
const int k = 3;
runAll<Method<SensorType, &SensorType::updat2>...>(k);
}
void printStats() {
// runAll<Method<SensorType, &SensorType::printStats>...>();
}
};
int main() {
{
BaseSensor<EdgeSensor,TrendSensor> ets;
ets.update();
ets.updat2();
ets.printStats();
}
{
BaseSensor<EdgeSensor> ets;
ets.update();
ets.updat2();
ets.printStats();
}
}
The above compiles and runs fine. 以上编译并运行良好。 The problem is: how can I gather the return values (std::strings) from running the mixin
SensorType::printStats()
methods in BaseSensor::printStats()
? 问题是:如何从
BaseSensor::printStats()
运行mixin SensorType::printStats()
方法收集返回值(std :: strings BaseSensor::printStats()
?
If I try to create a 2ndary version of the run*
functions and the Method
template, I fail to make it compile. 如果我尝试创建
run*
函数和Method
模板的第二版,我就无法编译它。 Say I did: 说我做了:
template <class T, void (T::*)()>
struct Method2 { };
template <class T, void(T::*M)()>
int runSingle2(Method2<T, M>) {
(this->*M)();
return 0;
}
template <class... Ts>
void runAll2() {
std::string s;
int run[sizeof...(Ts)] = { s = runSingle2(Ts{})... };
(void)run;
std::cout << "s=" << s << std::endl;
}
public:
void update() {
int k = 4;
runAll<Method<SensorType, &SensorType::update>...>(k);
}
void printStats() {
runAll2<Method2<SensorType, &SensorType::printStats>...>();
}
};
This does not compile saying 这不会编译说
g++ -Wall -Wextra -g -std=c++11 -c -o "obj_dbg/main.opp" "main.cpp"
main.cpp: In instantiation of ‘void BaseSensor<SensorType>::printStats() [with SensorType = EdgeSensor, TrendSensor]’:
main.cpp:65:20: required from here
main.cpp:58:8: error: could not convert template argument ‘&EdgeSensor::printStats’ to ‘void (EdgeSensor::*)()’
make: *** [obj_dbg/main.opp] Error 1
So HOW can I grab the return values from SensorType::printStats()
? 那么我如何从
SensorType::printStats()
获取返回值?
Here is you code reviewed so as it works as requested: 以下是您审核的代码,以便按要求运行:
#include<iostream>
#include <string>
#include <vector>
struct EdgeSensor
{
void update(int i) { std::cout << "EdgeSensor::update " << i << std::endl; }
void updat2(const int i ) { std::cout << "EdgeSensor::updat2" << i << std::endl; }
std::string printStats() { std::cout << "EdgeSensor::printStats" << std::endl;
return std::string("EdgeSensor::printStats"); }
};
struct TrendSensor
{
void update(int i ) { std::cout << "TrendSensor::update" << i << std::endl; }
void updat2(const int i ) { std::cout << "TrendSensor::updat2" << i << std::endl; }
std::string printStats() { std::cout << "TrendSensor::printStats" << std::endl;
return std::string("TrendSensor::printStats"); }
};
template<typename ... SensorType>
class BaseSensor : public SensorType ... {
template<typename F>
struct Invoke;
template<typename R, typename... A>
struct Invoke<R(A...)> {
template <R(SensorType::* ...M)(A...), typename T>
static std::vector<R> run(T *t, A... args) {
std::vector<R> vec;
int arr[] = { (vec.push_back((t->*M)(args...)), 0)... };
(void)arr;
return vec;
}
};
template<typename... A>
struct Invoke<void(A...)> {
template <void(SensorType::* ...M)(A...), typename T>
static void run(T *t, A... args) {
int arr[] = { ((t->*M)(args...), 0)... };
(void)arr;
}
};
public:
void update() {
Invoke<void(int)>::template run<&SensorType::update...>(this, 2);
}
void updat2() {
const int k = 3;
Invoke<void(int)>::template run<&SensorType::updat2...>(this, k);
}
void printStats() {
auto vec = Invoke<std::string(void)>::template run<&SensorType::printStats...>(this);
for(auto &&v: vec) {
std::cout << "--->" << v << std::endl;
}
}
};
int main() {
{
BaseSensor<EdgeSensor,TrendSensor> ets;
ets.update();
ets.updat2();
ets.printStats();
}
{
BaseSensor<EdgeSensor> ets;
ets.update();
ets.updat2();
ets.printStats();
}
}
I refactored a bit the code, for there was no need for the Method
class. 我重构了一些代码,因为不需要
Method
类。 This works as intended and the strings returned by the printStats
methods are now collected in a std::vector
and returned to the caller. 这按预期工作,
printStats
方法返回的字符串现在收集在std::vector
并返回给调用者。
To extend the solution to any type of member function you could do (and actually a bit simplify it still having in mind c++11 restriction). 要将解决方案扩展到您可以做的任何类型的成员函数(实际上有点简化它仍然考虑到c ++ 11限制)。 The approach resolves type of member function to be able to infer its result type.
该方法解析了成员函数的类型,以便能够推断其结果类型。 It also uses
InferOwnerType
to infer mixin type and avoid direct passing of statically casted this
pointer. 它还使用
InferOwnerType
来推断mixin类型,并避免直接传递静态转换this
指针。 Depending on the result of the member function now we can store it into an array or use the trick with int
array just to be sure each member function is invoked. 根据成员函数的结果,我们现在可以将它存储到数组中,或者使用
int
数组的技巧,以确保调用每个成员函数。
#include <iostream> // std::cout std::endl
#include <string> // std::string
#include <utility> // std::declval
struct EdgeSensor //a mixin
{
void update(int a){ std::cout << "EdgeSensor::update" << a << std::endl; }
std::string updat2(int const v) { return "EdgeSensor::printStats"; }
};
struct TrendSensor //another mixin
{
void update(int a){ std::cout << "TrendSensor::update" << std::endl; }
std::string updat2(int const v) { return "TrendSensor::printStats"; }
};
template <class Res, class This, class... Args>
This InferOwnerType(Res (This::*foo)(Args...)) { }
template<typename ... SensorType>
class BaseSensor : public SensorType ... //to my BaseSensor class
{
template <class M, class... Args>
auto run(M m, Args... args)
-> decltype((std::declval<decltype(InferOwnerType(m))*>()->*m)(args...)) {
return (static_cast<decltype(InferOwnerType(m))*>(this)->*m)(args...);
}
public:
template <class... Args>
void update(Args... args) {
int arr[] = {(run(&SensorType::update, args...), 0)...};
(void)arr;
}
template <class... Args>
void updat2(Args... args) {
std::string s[] = {run(&SensorType::updat2, args...)...};
for (int i = 0; i < sizeof...(SensorType); i++)
std::cout << s[i] << std::endl;
}
};
int main() {
BaseSensor<EdgeSensor, TrendSensor> bs;
bs.update(4);
bs.updat2(0);
BaseSensor<EdgeSensor> bs2;
bs2.update(1);
bs2.updat2(0);
}
Not sure if you can use c++11, if so, then I think this is the easiest? 不确定你是否可以使用c ++ 11,如果是这样,那么我认为这是最简单的吗?
#include <iostream>
#include <string>
struct EdgeSensor
{
void update(int i) { std::cout << "EdgeSensor::update " << i << std::endl; }
void updat2(const int i ) { std::cout << "EdgeSensor::updat2" << i << std::endl; }
std::string printStats() { std::cout << "EdgeSensor::printStats" << std::endl;
return std::string("EdgeSensor::printStats"); }
};
struct TrendSensor
{
void update(int i ) { std::cout << "TrendSensor::update" << i << std::endl; }
void updat2(const int i ) { std::cout << "TrendSensor::updat2" << i << std::endl; }
std::string printStats() { std::cout << "TrendSensor::printStats" << std::endl;
return std::string("TrendSensor::printStats"); }
};
template<typename ... SensorType>
class BaseSensor : public SensorType ... //to my BaseSensor class
{
public:
void update() {
auto v = { (static_cast<SensorType*>(this)->update(1), 0)... }; // *
(void) v;
}
void updat2() {
const int k = 3;
auto v = { (static_cast<SensorType*>(this)->updat2(k), 0)... }; // *
(void) v;
}
void printStats() {
auto v = { static_cast<SensorType*>(this)->printStats()... };
for (auto s : v) {
std::cout << s << std::endl;
}
}
};
int main() {
{
BaseSensor<EdgeSensor,TrendSensor> ets;
ets.update();
ets.updat2();
ets.printStats();
}
{
BaseSensor<EdgeSensor> ets;
ets.update();
ets.updat2();
ets.printStats();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.