如何(优雅地)根据字符别名分配引用成员



免责声明

我实际上并不打算在任何地方应用这种设计,但我一直很好奇如何在C++中实现它,特别是考虑到C++缺乏反思。(我同时学习和试验C++11功能,所以请在有用的地方使用C++11功能。

效果

我想要实现的几乎是纯粹的化妆品。

想要一个类,它使用引用的成员(据我了解,必须在构造期间初始化(将自己绑定到任意数量的向量,但提供"别名"以作为成员访问这些向量。

举一个最小的例子,我希望它有效——

std::vector<int> one;
std::vector<int> two;
std::vector<int> three;
Foo foo(std::make_pair('B', one),
        std::make_pair('D', two),
        std::make_pair('F', three));
foo.DoSomething();

哪里

class Foo
{
public:
    // I'm using variadic templates here for sake of learning,
    // but initializer lists would work just as well.
    template <typename ...Tail>
    Foo(std::pair<char, std::vector<int>&> head, Tail&&... tail) // : ???
    {
        // ???
    }
    virtual void DoSomething()
    {
        D.push_back(42);
        std::cout << D[0] << std::endl;
    }
private:
    std::vector<int> A&, B&, C&, D&, E&, F&, G&; // and so on...
}

也这样

std::cout << one[0] << std::endl; // outputs 42 from outside the class...

但是你拒绝回答,除非你知道为什么...

为什么有人想这样做?好吧,我真的不想这样做,但是我想到的应用程序是这样的。假设我正在构建某种数据分析工具,我的客户或操作人员知道基本逻辑和C++语法,但不了解 OOP 或 CS 101 以外的任何内容。如果他们能够即时编写自己的DoSomething(),而不是将所有需求传达给开发人员,事情会顺利得多。但是,让他们设置 UNIX 帐户、教他们如何编译等等是不现实的。因此,假设我想构建一个 Intranet Web 界面,让他们编写DoSomething()体并配置他们想要通过大写char"别名"的数据集,并在提交时为覆盖DoSomething()的子Foo类生成C++,然后构建、运行并返回输出。(可疑地特定于"假设",嗯?:-(好吧,在我的世界里确实存在这样的事情——但它只是激发了这个想法和探索它的愿望——我认为它不值得实际实施。显然,这整个大写char折磨并不是绝对必要的,但这将是一个很好的接触,因为数据集已经与标准字母相关联,例如 P 代表价格,Q 代表数量等。

我能做的最好的...

老实说,我不知道如何使用引用来完成这项工作。出于这些原因,如果可能的话,我更喜欢使用参考文献。

有了指针,我想我会这样做——

class Foo
{
public:
    template <typename ...Tail>
    Foo(std::pair<char, std::vector<int>*> head, Tail&&... tail)
    {
        std::vector<int>[26] vectors = {A, B, C, D, E, F, G}; // and so on...
        // I haven't learned how to use std::forward yet, but you get the picture...
        // And dear lord, forgive me for what I'm about to do...
        vectors[tail.first - 65] = tail.second;
    }
    virtual void DoSomething()
    {
        D->push_back(42);
        std::cout << (*D)[0] << std::endl;
    }
private:
    std::vector<int> A*, B*, C*, D*, E*, F*, G*; // and so on...
}

但即使这样也不是那么优雅。

  1. 有没有办法使用引用并实现这一点?

  2. 有没有办法使其更通用,例如使用伪反射方法来避免再次列出所有大写字母?

  3. 关于以更优雅或紧凑的方式保留主要目标(我描述的外观别名(的替代设计的任何建议?

你可以使用这样的东西:

class Foo
{
public:
    template <typename ...Ts>
    Foo(Ts&&... ts)  : m({std::forward<Ts>(ts)...}),
    A(m.at('A')),
    B(m.at('B'))
    // and so on...
    {
    }
    virtual void DoSomething()
    {
        A.push_back(42);
        std::cout << A[0] << std::endl;
    }
private:
    std::map<char, std::vector<int>&> m;
    std::vector<int> &A, &B; //, &C, &D, &E, &F, &G; // and so on...
};

但这需要给出每个向量,所以

Foo(std::vector<int> (&v)[26]) : A(v[0]), B(v[1]) // and so on...
{
}

Foo(std::vector<int> &a, std::vector<int> &b /* And so on */) : A(a), B(b) // and so on...
{
}

似乎更合适。

活生生的例子。

如果是拥有vector的类Foo,似乎更简单,所以你只会有

class Foo
{
public:
    virtual ~Foo() {}
    virtual void DoSomething() { /* Your code */ }
    std::vector<int>& getA() { return A; }
private:
    std::vector<int> A, B, C, D; // And so on 
};

并提供 getter 来初始化内部向量。

然后

std::vector<int>& one = foo.GetA(); // or foo.A if you let the members public.

相关内容

  • 没有找到相关文章

最新更新