如何编写一个替换链式方法调用的可变方法
How to write a variadic method which replaces chained method calls?
我正在开发一个名为group_by
的递归映射类,该类为SQL同名对象建模
例如,gb是一个group_by
对象,它将存储指向按std::string
、int
和char
密钥类型分组的foo
的指针。
group_by<foo,std::string,int,char> gb;
group_by
提供了一种at( I const& key )
访问器方法,可用于查看当前级别映射内部。链接at()
调用以检索更深层次的映射效果良好。
auto& v = gb.at( k1 ).at( k2 ).at( k3 ).get_vec();
问题
我想创建一个名为at_variadic( Args const& ...args )
的at()
的替代方案,它可以在一次调用中检索更深层次的映射,而无需链接
auto& w = gb.at_variadic( k1, k2 );
auto& x = gb.at_variadic( k1, k2, k3 );
然而,我遇到了一些问题。首先,我不知道如何指定返回类型,因为它取决于可变参数。也许以某种方式使用decltype()
?
工作答案
Ecatmur下面的回答概述了一个好方法。
为了让编译器满意,我不得不摆弄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++:使用方法调用析构函数的顺序是什么?
- 派生类调用父类的方法,该方法调用重写的虚拟方法调用错误的方法
- 使用 object 中的方法调用带有 std::bind 和 std::function.target 的 C 样式函数
- 指向类方法调用的指针
- 如何使用 SFINAE 在方法调用中有条件地定义变量?
- 是否有可以处理方法调用依赖关系的设计模式?
- 如何缩短C++中的方法调用?
- 从部分专用模板方法调用模板非静态方法
- 有没有办法禁止派生类中的基类方法调用?
- 为什么这C++只在编译器上编码一个不明确的方法调用Microsoft?
- 从父方法调用子方法
- 如何将子方法调用到父方法
- 虚拟函数在哪里使用 vpointer to vtable 来解析方法调用,非虚拟方法存储在哪里以及如何解析它们?
- 从静态方法调用静态函数指针
- 从同一类中的另一个方法调用方法时出错
- 方法调用意外地像 l 值一样起作用
- 无法从派生的一个方法调用基类方法
- 从类方法调用命名空间中名为 Same 的函数时,重载解析失败
- C 多线程JAVA JNI方法调用