我开始使用example available here并修改它以获取以下代码:
#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);
}
任何人都可以解释为什么这个特定(修改过的)示例会因分段错误而崩溃吗?如果我编译它,即使使用-Wall with g ++ 4.x,我也不会收到任何类型的警告。
答案 0 :(得分:7)
我会将您的代码简化为一个简单的示例:
#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());
}
答案 1 :(得分:1)
带签名
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());
}
递归调用自己直到崩溃。
答案 2 :(得分:0)
在Valgrind下运行程序会显示由此行引起的堆栈溢出:
work_dispatch(3.0);
执行此行:work_dispatch(typename traits<T>::tag());
一遍又一遍(导致堆栈溢出)。
编辑:我认为您应该尝试使用以下修补程序:
#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);
}
也就是说,你应该:
T
参考)答案 3 :(得分:0)
template <typename T>
void work_dispatch(const slow_tag)
{
std::cout << "Slow function" << std::endl;
}
编译器无法确定此函数中的T
应该是什么,因此在重载决策中不会考虑它。
并且您不会收到任何错误,因为&#34;替换失败不是错误&#34;。