gpt4 book ai didi

c++ - 如何编写替换链式方法调用的可变参数方法?

转载 作者:可可西里 更新时间:2023-11-01 18:37:55 25 4
gpt4 key购买 nike

我正在研究一个名为 group_by 的递归 map 类它模拟 SQL 同名。

例如,gb 是一个group_by将存储指向 foo 的指针的对象按 std::string 分组, int , 和 char键类型,按此顺序。

group_by<foo,std::string,int,char>  gb;

group_by提供一个 at( I const& key )可用于查看当前级别 map 内部的访问器方法。链接 at()检索更深层 map 的调用工作正常。

auto& v = gb.at( k1 ).at( k2 ).at( k3 ).get_vec();

问题

我想创建 at() 的替代品称为 at_variadic( Args const& ...args )它可以在一次调用中检索所有更深层次的 map ,而无需链接。

auto& w = gb.at_variadic( k1, k2 );
auto& x = gb.at_variadic( k1, k2, k3 );

但是,我遇到了一些问题。首先,我不知道如何指定返回类型,因为它取决于可变参数。也许使用 decltype() , 不知何故?

工作答案

Ecatmur's answer below概述了一个好的方法。

我不得不尝试使用 group_by<> 的终端机壳为了让编译器满意,但下面的代码在很大程度上基于 Ecatmur 的回答,似乎在 gcc 4.7.2 上运行良好。

#include <cassert>
#include <map>
#include <vector>
#include <iostream>

template< typename T, typename... Args >
struct group_by
{
using child_type = T;

std::vector<T*> m_vec;

void insert( T* t )
{
m_vec.push_back( t );
}

child_type&
at( size_t i )
{
return *m_vec[i];
}
};

template< typename T, typename I, typename... Args >
struct group_by<T,I,Args...>
{
using child_type = group_by<T,Args...>;

std::map<I,child_type> m_map;

void insert( T* t )
{
m_map[ *t ].insert( t );
}

child_type& at( I const& key )
{
return m_map.at( key );
}

template<typename... Ks>
auto
at( I const& i, Ks const&...ks )
-> decltype( m_map.at( i ).at( ks... ) )
{
return m_map.at( i ).at( ks... );
}
};

// -----------------------------------------------------------------------------

struct foo
{
std::string s;
int i;
char c;

operator std::string() const { return s; }
operator int () const { return i; }
operator char () const { return c; }

bool operator==( foo const& rhs ) const
{
return s==rhs.s && i==rhs.i && c==rhs.c;
}
};

int main( int argc, char* argv[] )
{
foo f1{ "f1", 1, 'z' };
foo f2{ "f2", 9, 'y' };
foo f3{ "f3", 3, 'x' };
foo f4{ "f1", 4, 'k' };

group_by<foo,std::string,int,char> gb;

gb.insert( &f1 );
gb.insert( &f2 );
gb.insert( &f3 );
gb.insert( &f4 );

std::string k1{ "f1" };
int k2{ 1 };
char k3{ 'z' };

auto& a = gb.at( k1 ).at( k2 ).at( k3 ).at( 0 );
auto& b = gb.at( k1 ).at( k2 ).m_map;
auto& c = gb.at( k1 ).m_map;
auto& d = gb.at( k1, k2 ).m_map;
auto& e = gb.at( k1, k2, k3 ).m_vec;
auto& f = gb.at( k1, k2, k3, 0 );

assert( a==f1 );
assert( b.size()==1 );
assert( c.size()==2 );
assert( d.size()==1 );
assert( e.size()==1 );
assert( f==f1 );

return 0;
}

最佳答案

链式方法调用本质上是递归的,所以你需要递归地实现at:

child_type& at( I const& key ) {
return m_map.at( key );
}

template<typename J, typename... Ks>
auto at(const I &i, const J &j, const Ks &...ks)
-> decltype(m_map.at(i).at(j, ks...)) {
return m_map.at(i).at(j, ks...);
}

请注意,由于 at 至少需要 1 个参数,因此可变参数形式至少需要 2 个参数。这比在 sizeof... 上调度要容易得多,而且应该更容易阅读。

关于c++ - 如何编写替换链式方法调用的可变参数方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14934749/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com