Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this template have an error in Xcode but not Visual Studio?

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);
}
like image 972
gauss256 Avatar asked Dec 28 '22 09:12

gauss256


2 Answers

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.

like image 200
wilhelmtell Avatar answered Jan 14 '23 13:01

wilhelmtell


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.

like image 25
Georg Fritzsche Avatar answered Jan 14 '23 14:01

Georg Fritzsche