在类上启用std :: get支持

时间:2013-04-23 15:53:50

标签: c++ c++11 stdtuple

我必须专门支持std :: get?

的模板是什么
struct MyClass {
  int a;
};

template <const size_t I>
struct MyContainer {
  MyClass array[I];
};

我有什么专长才能做到:

MyContainer<16> mc;
std::get<0>(mc);

2 个答案:

答案 0 :(得分:13)

std::get不是标准库的自定义点;三个函数模板重载(对于pairtuplearray)没有明确允许用户定义的重载,所以17.6.4.2.1p1适用并添加自己函数的声明模板重载是未定义的行为。

请注意,get作为非限定名称​​是自C ++ 17开始的自定义点;它由structured binding declaration协议用于访问类似元组的元素;但这是一个不合格的名称,而不是合格的名称std::get

那就是说,如果你 写:

namespace std {
   template<size_t I, size_t N> MyClass &get(MyContainer<N> &c) { return c.array[I]; }
}

并且类似于rvalue引用和const引用重载,您的程序可能会按预期工作。

然而,由于标准已经提供array

,因此可以看到一点点
template<size_t N> using MyContainer = std::array<MyClass, N>;

答案 1 :(得分:0)

我猜你想要实现一些需要使用编译时索引访问任意类数组容器的算法,因此我们的目的是使用某些函数(如std::get)来实现统一执行那项任务?! 在这种情况下,与为您的班级提供beginend的业务相同。您只需在声明容器类的命名空间中声明函数get,然后让ADL完成其工作。

    template <unsigned I, unsigned N>
    MyClass& get (MyContainer<N>& c) { return c.array[I]; }

    template <unsigned I, unsigned N>
    MyClass const& get (MyContainer<N> const& c) { return c.array[I]; }

在您的算法中,您只需使用get(不带std命名空间前缀),ADL将调用正确的函数。因此,对于array这样的标准结构,我会调用tuplepair std::get,并为您的容器调用您提供的get函数。

    int main(){
        std::array<int, 3> a {{0,1,2}};
        auto t = std::make_tuple(0.0, 1.0f, 2);
        auto p = std::make_pair('0', 4.4);
        MyContainer<3> c;

        std::cout << get<1>(a) << std::endl;
        std::cout << get<1>(t) << std::endl;
        std::cout << get<1>(p) << std::endl;
        std::cout << get<1>(c).a << std::endl;

        return 0;
    }

Example