10

我必须专门使用哪些模板来支持 std::get?

struct MyClass {
  int a;
};

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

我必须专攻什么才能做到:

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

2 回答 2

16

std::get不是标准库的定制点;三个函数模板重载(forpair和)不明确允许用户定义的重载,因此 17.6.4.2.1p1 适用并且添加您自己的函数模板重载的声明是未定义的行为tuplearray

请注意,get作为非限定名称C++17 的自定义点;结构化绑定声明协议使用它来访问类似元组的元素;但这是一个非限定名称,而不是限定名称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>;
于 2013-04-23T16:43:11.017 回答
1

我猜你想实现一些算法,这些算法需要使用编译时索引访问任意类似数组的容器,因此旨在使用一些函数(如std::get)来统一执行该任务?!在这种情况下,它与为您的班级制作begin和提供相同的业务。end您只需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;
    }

例子

于 2013-04-24T08:30:42.273 回答