C ++模板参数作为成员指针将是按引用调用的有效方法吗?

时间:2019-06-09 22:06:14

标签: c++ templates compilation metaprogramming

template<class T, typename... Args>
class Wrapper
{
    // simple way of representing pointer-to-member
    template <class T, class V>
    using mv = V T::*;
public:
    // non-type arguments (which are pointers to member)
    template<mv<T, Args>... Ptrs> 
    static void fun(T* t)
    {
        make_tuple(t->*Ptrs...);
    }
};

// inefficient one
template <typename... Args>
void fun_dynmaic_(Args&... args)
{
    make_tuple(args...);
}

// actual class
class Apple
{
    int a; float b; string c;
public:
    Apple(int a, float b, const string& c) : a(a), b(b), c(c) {}

    void fun_dynamic()
    {
        fun_dynmaic_(a, b, c);
    }
    void fun_static1()
    {
        make_tuple(a, b, c);
    }
    void fun_static2()
    {
        Wrapper<Apple, int, float, string>::fun<&Apple::a, &Apple::b, &Apple::c>(this);
    }
};

我要处理某个类的所有成员变量。

简单地假设它是make_tuple()

在这里,我带来了3种实现方法。 我不确定,但是经过编译优化和内联之后,fun_static1()fun_static2()将被编译成几乎相同的高效机器代码。就像这样:指向Apple的指针,并使用实体偏移量直接访问每个成员。

fun_dynamic()效果很好,但带有变量的所有地址。因此它必须是低效的。

在大多数情况下,选择fun_static1()似乎是最好的。简单,快捷。但是,在某些情况下,我可能会有一些巨大的需求。例如,有class Banana, class Orange ...,并且该任务(应在Apple, Banana..的所有成员上完成)可能非常复杂但可重用的例程(而不仅仅是make_tuple())。如果那样的话,我必须要有一个模板。

在这种情况下,不能使用

fun_static1()。如果我关心运行时性能,则必须选择fun_static2()而不是fun_dynamic()。对吧?

最后,

  1. 我利用了一个事实,即指向成员的指针是constexpr,因此可以作为模板的参数。
  2. 因此,我可以构建一个模拟 fun_static1()的功能模板。
  3. 现在我不必传递每个成员的实际地址。相反,实例化的函数将具有固定偏移量并可以直接使用它。
  4. 它不会浪费任何运行时资源,并且不会用void*来计算成员偏移量。

我是对的吗?那么,每当我认真考虑运行时性能时,是否应该实际实现fun_static2()? (我永远不会这么做,只是出于好奇)

编辑-如果您不需要模板,只需简单地以为我想在fun_dynmaic_()上重用 Apple'的成员,Banana等等。然后,如果有很多变量,则实施fun_static2()而不是fun_dynamic()会很麻烦,但是(似乎)是更快的解决方案。

Edit2 -三种功能的作用完全相同:复制 a,b,c的并放入一个元组。 (这只是一个例子)

0 个答案:

没有答案