I am getting an error in Xcode when using templates in C++. Can someone tell me what is wrong?
The first version reports an error in Xcode, but not in Visual Studio.
// Version 1: Error in Xcode, but not Visual Studio
template<typename LengthT, typename VertexT>
int MyGraphAlgorithm(...arguments omitted...)
{
using namespace boost;
typedef property<vertex_distance_t, LengthT> VertextProperties_t;
typedef adjacency_list<vecS, vecS, directedS, VertextProperties_t> Graph;
// In next line Xcode reports: "error: expected `;' before 'vertexInitial'"
graph_traits<Graph>::vertex_descriptor vertexInitial(100);
}
The second has no error. The difference is the use of the template parameter LengthT in a templated typedef.
// Version 2: No error in Xcode or Visual Studio
template<typename LengthT, typename VertexT>
int MyGraphAlgorithm(...arguments omitted...)
{
using namespace boost;
// In the following line, LengthT has been changed to int
typedef property<vertex_distance_t, int> VertextProperties_t;
typedef adjacency_list<vecS, vecS, directedS, VertextProperties_t> Graph;
graph_traits<Graph>::vertex_descriptor vertexInitial(100);
}
The reason for the error is that the compiler has no clue what graph_traits<Graph>::vertex_descriptor
is. Is it a static member or a type? If it's a type then you must say so:
typename graph_traits<Graph>::vertex_descriptor
The reason the compiler isn't smart enough to figure it out on its own is because LengthT
is a template parameter. It can be anything, and so at the time of template declaration the compiler can't tell what its value is going to be, and the typedef is thus ambiguous.
vertex_descriptor
is a dependent type (it depends on the template argument LengthT
), thus you have to use typename
:
typename graph_traits<Graph>::vertex_descriptor vertexInitial(100);
In the second example the depency on the template argument is removed (you use a fixed type instead - int
), thus there is no error.
A much simpler way to reproduce that:
template<class T> struct A { typedef T type; };
template<class T> struct B {
A<T>::type t1; // wrong, works with VS but not with conforming compilers
typename A<T>::type t2; // correct
};
Visual Studio is known to be non-conforming in that regard and is "great" for developing non-portable template code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With