使用模板成员

时间:2017-12-17 21:48:12

标签: c++ templates

像这样的类模板

template <typename... T>
class Action {
private:        
    std::tuple<T...> m_args;
public:
    Action(T... args) : m_args(args...) {}
}

到具有模板成员的类。这样做的原因是只想制作一种类,因此具有不同args的对象仍然属于同一个类,以便于操作。

class Action {
private:       
    // this does not work, how to declare the tuple type so that It can hold any arguments list.
    template <typename... T>
    std::tuple<T...> m_args;
public:   
    template <typename... T>
    Action(T... args) : m_args(args...) {}
}

1 个答案:

答案 0 :(得分:0)

将您的想法放在编译器的角度。我们可信赖的朋友如何知道Action需要多少存储空间,如果该大小取决于解析的构造函数?这是不可能的。

template<typename... T>
Action(T... args) : m_args(args...) {}

// wait what???
Action(int someArg) : m_args(someArg) {}

假设第二个构造函数是有效的,或者我们有两个Action个对象,其中不同的参数传递给构造函数 - 应该是sizeof(Action)

如果你遇到这样的问题,可以考虑编译器:可能有些人必须给出足够好的理由,说明为什么不应该支持它,只是因为它只会使实现变得复杂并且还具有性能影响。

由于您提到使用指针而不是聚合对象,我想我会告诉您如何完成此操作。请注意,这会影响性能,因为您现在正在堆上为m_args分配内存,而不是堆栈。

class Action
{
public:
    template<typename... T>
    using TArgs = std::tuple<T...>;

    std::shared_ptr<void> m_args;

    template<typename... T>
    Action(T... args) 
        : m_args(std::make_shared<TArgs<T...>>(args...)) {}
};

Action myAction(1, 2.0, 3.5f);

auto *myActionArgs = 
    static_cast<Action::TArgs<int, double, float>*>(myAction.m_args.get());

// 2.0
double secondArg = std::get<1>(*myActionArgs);

维护看起来并不好玩。