I started to play with the example available here and modified it to get the following code:
#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);
}
Can anyone explain my why this particular (modified) example crashes with a segmentation fault? If I compile it I don't get any type of warning even when using -Wall with g++ 4.x.
I'll reduce your code to a simple example:
#include <iostream>
template <typename T>
void work_dispatch(double)
{
std::cout << "Slow function" << std::endl;
}
int main()
{
work_dispatch(3.0);
}
Compile error:
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.
In other words you can't call this template
template <typename T>
void work_dispatch(double)
{
std::cout << "Slow function" << std::endl;
}
with
work_dispatch(3.0);
since there is no way you can deduce the type T
, nor you're passing it explicitly. Therefore you have a stack overflow due to an infinite recursion:
template <typename T>
void work_dispatch(const T) <----------------|
{ | This ends up calling itself
work_dispatch(typename traits<T>::tag()); -|
}
To fix your code the easiest solution is to provide the type yourself
template <typename T>
void work_dispatch(const T)
{
work_dispatch<T>(typename traits<T>::tag());
}