这是"Tag Dispatching"吗?
Is this "Tag Dispatching"?
假设我有一些代码:
void barA() { }
void barB() { }
void fooA() {
// Duplicate code...
barA();
// More duplicate code...
}
void fooB() {
// Duplicate code...
barB();
// More duplicate code...
}
int main() {
fooA();
fooB();
}
我想删除fooA
和fooB
之间的重复代码,我可以使用一些动态技术,如传入bool参数,传递函数指针或虚拟方法,但如果我想要一个编译时的技术,我可以这样做:
struct A { };
struct B { };
template<typename Tag> void bar();
template<> void bar<A>() { }
template<> void bar<B>() { }
template<typename Tag> void foo() {
// Duplicate code
bar<Tag>();
// More duplicate code
}
int main() {
foo<A>();
foo<B>();
}
在中,我引入了两个空的"标签"类来指示使用哪个bar
,并基于标签类模板化foo
和bar
。这似乎奏效了。问题:
- 这个技术有名字吗?这是"标签调度"的一个例子吗?从我读到的关于标签调度的内容来看,它略有不同,涉及到带有标签参数的函数重载。一个可能来自trait类中的类型定义的标签。
- 是否有一种更典型的编译时技术来实现同样的事情?
另一种可能性是使用bar
的函数重载而不是模板特化,并将标记类作为参数传递:
struct A { };
struct B { };
void bar(A) { }
void bar(B) { }
template<typename Tag> void foo() {
// Duplicate code
bar(Tag());
// More duplicate code
}
int main() {
foo<A>();
foo<B>();
}
这不是标签调度。正如你在你的问题中正确地说,如果你使用A
和B
的一些编译时特性来区分两者,然后使用它来选择两种不同的重载。
标签调度的一个很好的例子是std::advance
的典型实现方式。函数的签名是
template< class InputIt, class Distance >
void advance( InputIt& it, Distance n );
如果满足RandomAccessIterator的要求, it
可以在单次操作中增加n
的位置。对于较小的迭代器,必须在循环中推进it
。因此,实现可能会做类似于以下的事情:
namespace detail
{
template<class InputIt, class Distance>
void advance(InputIt& it, Distance n, std::random_access_iterator_tag)
{
it += n;
}
template<class InputIt, class Distance>
void advance(InputIt& it, Distance n, std::bidirectional_iterator_tag)
{
if(n < 0) {
while(n++) --it;
} else {
while(n--) ++it;
}
}
template<class InputIt, class Distance>
void advance(InputIt& it, Distance n, std::input_iterator_tag)
{
assert(n >= 0);
while(n--) ++it;
}
}
template< class InputIt, class Distance >
void advance( InputIt& it, Distance n )
{
detail::advance(it, n,
typename std::iterator_traits<InputIt>::iterator_category());
}
我不知道你在做什么具体的名字。这只是一个如何遵循DRY原则的例子。
如果bar
将A
和B
的实例作为参数,那么我将以不同的方式实现它。我不想让bar
成为一个函数模板,然后提供专门化,而是让重载解析为我完成这项工作。
void bar(A const&) { ... }
void bar(B const&) { ... }
但既然不是这样,提供显式专门化似乎是正确的方法。
相关文章:
- 使用递归的数组的最小值.这是怎么回事
- 我不小心调用了一个没有自己类对象的成员函数.但这是怎么回事呢
- 这是我尝试让用户将值输入到数组中.然后将其隐藏为大量的星号
- 这是实现图形的坏方法吗
- 当基类是依赖类型时,这是一个缺陷吗
- 当C++中需要自动删除时,这是静态的正确用法吗?
- 这是关于成员访问规则的正确摘要吗
- 这是插入排序的正确实现吗?
- 我使用 OpenMP 的线程越多,执行时间就越长,这是怎么回事?
- 如何在OpenCV中检测这是谁的脸?
- 这是使用回溯的 nqueen 问题,但我使用了动态 2d 数组,我的程序编译良好,但不返回任何输出
- 在 Python 和 c++ 2d 数组初始化之间.这是怎麽?为什么呢?
- 验证openssl c++中的签名,这是由JAVA DSA签名的?
- 这是GoogleTest AssertionResult中的错误吗?
- 在编译时,C++项目抛出错误 C2228,这是预期的,因为控件在运行时未达到该点
- 这是 basic.def.odr 部分的缺陷吗?
- 被覆盖的函数不会反映在基类中,这是正常行为吗?
- MSVC 无法根据模板参数进行数学运算,这是一个错误吗?
- 这是 ubuntu 16.04 中的 gdb 错误吗?
- 这是"Tag Dispatching"吗?