C++中的标记调度示例
Tag dispatching example in C++
我开始使用这里提供的示例,并对其进行了修改以获得以下代码:
#include <iostream>
struct slow_tag {};
struct fast_tag {};
template <typename T>
struct traits
{
typedef slow_tag tag;
};
template <>
struct traits<int>
{
typedef fast_tag tag;
};
template <typename T>
void work_dispatch(const slow_tag)
{
std::cout << "Slow function" << std::endl;
}
template <typename T>
void work_dispatch(const fast_tag)
{
std::cout << "Fast function" << std::endl;
}
template <typename T>
void work_dispatch(const T)
{
work_dispatch(typename traits<T>::tag());
}
int main()
{
std::cout << "Starting my program" << std::endl;
work_dispatch(3.0);
work_dispatch(3);
}
有人能解释我为什么这个特殊的(修改的(例子会因为分段错误而崩溃吗?如果我编译它,即使在使用带有g++4.x的-Wall时,我也不会得到任何类型的警告。
我将把您的代码简化为一个简单的例子:
#include <iostream>
template <typename T>
void work_dispatch(double)
{
std::cout << "Slow function" << std::endl;
}
int main()
{
work_dispatch(3.0);
}
编译错误:
main.cpp:11:3: error: no matching function for call to 'work_dispatch'
work_dispatch(3.0);
^~~~~~~~~~~~~
main.cpp:4:6: note: candidate template ignored: couldn't infer template argument 'T'
void work_dispatch(double)
^
1 error generated.
换句话说,你不能称这个模板为
template <typename T>
void work_dispatch(double)
{
std::cout << "Slow function" << std::endl;
}
带有
work_dispatch(3.0);
由于无法推导类型T
,也无法显式传递它。因此,由于无限递归导致堆栈溢出:
template <typename T>
void work_dispatch(const T) <----------------|
{ | This ends up calling itself
work_dispatch(typename traits<T>::tag()); -|
}
要修复您的代码,最简单的解决方案是提供自己类型的
template <typename T>
void work_dispatch(const T)
{
work_dispatch<T>(typename traits<T>::tag());
}
示例
带有签名
template <typename T>
void work_dispatch(const slow_tag);
T
无法推导,因此您必须在调用中提供它
template <typename T>
void work_dispatch(const T)
{
work_dispatch<T>(typename traits<T>::tag());
}
如目前
template <typename T>
void work_dispatch(const T)
{
work_dispatch(typename traits<T>::tag());
}
递归地调用自己,直到崩溃。
template <typename T>
void work_dispatch(const slow_tag)
{
std::cout << "Slow function" << std::endl;
}
编译器无法确定此函数中的T
应该是什么,因此在重载解析中不考虑它。
你不会得到任何错误,因为"替换失败不是错误"。
在Valgrind下运行程序表明,由于以下行导致堆栈溢出:
work_dispatch(3.0);
它一次又一次地执行这一行:CCD_ 4(导致堆栈溢出(。
编辑:我认为您在这里尝试做的事情应该可以通过以下修复:
#include <iostream>
struct slow_tag {};
struct fast_tag {};
template <typename T>
struct traits {
typedef slow_tag tag;
};
template <>
struct traits<int> {
typedef fast_tag tag;
};
template <typename T>
void work_dispatch(const T& val, const slow_tag& st) {
std::cout << "Slow function" << std::endl;
}
template <typename T>
void work_dispatch(const T& val, const fast_tag& ft) {
std::cout << "Fast function" << std::endl;
}
template <typename T>
void work_dispatch(const T& val) {
work_dispatch(val, typename traits<T>::tag());
}
int main() {
std::cout << "Starting my program" << std::endl;
work_dispatch(3.0);
work_dispatch(3);
}
也就是说,你应该:
- 做dispatch提供值(我还将函数参数更改为
T
引用( - 将值传递给从分派函数启动的两个模板化函数
相关文章:
- 如何在c++中实现处理器调度模拟器
- 如何在 C++17 STL 并行算法中处理调度?
- 无法使用迭代器标记调度实例化模板
- 在 c++11 中为 pthread 设置调度参数
- 如何在 assert() 和 static_assert() 之间调度,如果在 constexpr 上下文中依赖?
- 如何使用从处理程序调度的最终回调将响应异步返回给调用方on_read?
- C++双重调度
- 动态调度到模板函数C++
- 正确调度消息 UART
- 在 C++ 中使用枚举而不是结构进行标记调度
- 如何实现从 Windows 脚本主机到脚本的事件调度
- C++内置类型的基于类型的调度
- 用于GPU上的瓦片度量和调度的Halide
- SFINAE和标签调度之间的差异
- C++ 如何按标签调度到不同的模板函数
- 在 boost::asio 中发布和调度有什么区别?
- 5 CPU的任务调度N进程
- 究竟发生了什么,我们需要在 c++ 中双重调度/访客
- openMp 动态调度与按处理时间排序任务时的 LPT 调度相同吗?
- C++中的双重调度不起作用