【问题标题】:Compose data member access in C++在 C++ 中编写数据成员访问
【发布时间】:2018-11-20 17:14:25
【问题描述】:

我试图通过指向数据成员的指针迭代对象来访问数据成员。

这个想法是有一个可变参数模板函数,它在第一个 obj 上调用 std::invoke 并将结果传递给指向数据成员的下一个指针。 就像是

compose x fnList = foldl obj (\x f -> f x) fnList

来自功能世界。

我一路走来的事情是:

// main.hpp
#include <iostream>
#include <functional>
// initial template to stop recursion
template<typename T>
T getMember(T obj) {
  return obj;
}
// variadic template, where recursive application of 
// pointer to data member should happen
// I think return type should be something like "*Ret"
template<typename T, typename K, typename Ret, typename ... Args>
Ret getMember(T obj, K memberPointer, Args ... args) {
    return getMember(std::invoke(memberPointer, obj), args ...);
}

//main.cpp
#include <iostream>
#include "main.hpp"

//inner class
class Engine 
{
    public:
    std::string name;
};
// outer class
class Car
{
    public:
    int speed;
    Engine eng;
};

void main()
{
    Car car;
    car.speed = 1;        
    car.eng.name = "Some Engine Name";

    // should be same as call to id function, returning the only argument
    Car id = getMember(c1);
    // should "apply" pointer to data member to the object and
    // return speed of the car
    int speedOfCar = getMember(car, &Car::speed);
    // should "apply" pointer to data member to the car,
    // pass the resulting Engine further to &Engine::name,
    // return "Some Engine Name"
    std::string nameOfEngineOfCar = getMember(car, &Car::eng, &Engine::name);

    std::cout << nameOfEngineOfCar << std::endl;
}

编译无法推断返回类型Ret (gcc 5+, C++17) 甚至可能吗?有什么限制(C++14可以做到)?

【问题讨论】:

  • decltype(auto) 怎么样?
  • 这看起来是一个相当复杂的写car.eng.make的方法。

标签: c++ variadic-templates pointer-to-member


【解决方案1】:

你不能推导出只出现在函数返回类型位置的模板参数。但是模板参数推导并不是 C++ 中唯一的推导。你可以这样做:

template <class Bar, class Baz>
auto foo(Bar x, Baz y) 
      -> decltype(auto) { 
    return moo(x, y); 
}

如果由于旧编译器导致失败,则更安全的后备是

template <class Bar, class Baz>
auto foo(Bar x, Baz y)
     -> decltype(moo(x, y)) { 
    return moo(x, y); 
}

【讨论】:

  • " 由于旧的编译器"。您的意思是标准...在新编译器上使用类似于-std=c++03 的标志也会失败。 (那么确实,足够老的编译器不支持最新标准)
  • auto !就这么容易!谢谢。
猜你喜欢
  • 2014-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-01
  • 1970-01-01
相关资源
最近更新 更多