template problem linker, can it be a bug?

Hi all,

I am using gcc 4.6.3 on Ubuntu with standard settings.

I have the following program, which compiles just fine, but fails to link:
[Edit:] Minified from original post 1 time.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//main.cpp
class Integer
{
public:
  static unsigned int HashFunction(const Integer& input)
  { return 0;
  }
};

template <class Object, unsigned int hashFunction(const Object&)=Object::HashFunction>
class List
{
public:
  inline unsigned int GetHash(const Object& input)const
  { return hashFunction(input);
  }
};

template <class Object>
class ListSpecialized: public List<Object, Object::HashFunction>
{
};

template <class CoefficientType, unsigned int inputHashFunction(const CoefficientType&)= CoefficientType::HashFunction>
class Element
{
public:
  static inline unsigned int HashFunction(const Element<CoefficientType, inputHashFunction>& input)
  { CoefficientType x;
    return inputHashFunction(x);
  }
};

template<class CoefficientType>
class TheComputation
{
public:
  List<Element<Integer>, Element<Integer>::HashFunction >
  //ListSpecialized<Element<Integer> >
  theList;
};

int main()
{ TheComputation<Integer > A;
  Element<Integer> x;
  A.theList.GetHash(x);
  return 0;
}


The error message is (here it comes!):

main.o||In function `List<Element<Integer, &(Integer::HashFunction(Integer const&))>, &(Element<Integer, &(Integer::HashFunction(Integer const&))>::HashFunction(Element<Integer, &(Integer::HashFunction(Integer const&))> const&))>::GetHash(Element<Integer, &(Integer::HashFunction(Integer const&))> const&) const':|
main.cpp|14|undefined reference to `Element<Integer, &(Integer::HashFunction(Integer const&))>::HashFunction(Element<Integer, &(Integer::HashFunction(Integer const&))> const&)'|
||=== Build finished: 1 errors, 0 warnings ===|



Now, if I only change one line of code, it compiles and links just fine:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class Integer
{
public:
  static unsigned int HashFunction(const Integer& input)
  { return 0;
  }
};

template <class Object, unsigned int hashFunction(const Object&)=Object::HashFunction>
class List
{
public:
  inline unsigned int GetHash(const Object& input)const
  { return hashFunction(input);
  }
};

template <class Object>
class ListSpecialized: public List<Object, Object::HashFunction>
{
};

template <class CoefficientType, unsigned int inputHashFunction(const CoefficientType&)= CoefficientType::HashFunction>
class Element
{
public:
  static inline unsigned int HashFunction(const Element<CoefficientType, inputHashFunction>& input)
  { CoefficientType x;
    return inputHashFunction(x);
  }
};

template<class CoefficientType>
class TheComputation
{
public:
  //List<Element<Integer>, Element<Integer>::HashFunction >
  ListSpecialized<Element<Integer> >
  theList;
};

int main()
{ TheComputation<Integer > A;
  Element<Integer> x;
  A.theList.GetHash(x);
  return 0;
}



However, I expected that the two lines, although different, should have the same practical effect. That appears to be false.

What is going on?
Does the first version compile on other compilers?

The example is a bit long, but it is a minification from around 15k loc. If you can minify the code futher, please post!

Thanks,
tition
Last edited on
Compiles & links fine with MSVC 2010.
Just took a cursory look; on the basis of that, it does seem to be a bug in GCC.
Really need a lot more time to figure out exactly what is going on.

This code compiles and links cleanly:
1
2
3
4
5
6
7
8
9
10
11
12
struct integer { static inline int hash(const integer& input) { return 0 ; } };

template < class T, int HASH( const T&) = T::hash > struct list
{inline int hash( const T& t ) const { return hash(t) ; } } ;

template < class COEFF, int HASHFUN( const COEFF& ) = COEFF::hash > struct element
{ static inline int hash( const element<COEFF,HASHFUN>& input ) { return HASHFUN(input) ; } };

template < class COEFF >
struct computation { list< element<integer>, element<integer>::hash > lst ; } ;

int main() { computation<integer>().lst.hash( element<integer>() ) ; }


This equivalent code doesn't (gives the link error):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class Integer
{
public:
  static unsigned int HashFunction(const Integer& input)
  { return 0;
  }
};

template <class Object, unsigned int hashFunction(const Object&)=Object::HashFunction>
class List
{
public:
  inline unsigned int GetHash(const Object& input)const
  { return hashFunction(input);
  }
};

template <class Object>
class ListSpecialized: public List<Object, Object::HashFunction>
{
};

template <class CoefficientType, unsigned int inputHashFunction(const CoefficientType&)= CoefficientType::HashFunction>
class Element
{
public:
  static inline unsigned int HashFunction(const Element<CoefficientType, inputHashFunction>& input)
  { CoefficientType x;
    return inputHashFunction(x);
  }
};

template<class CoefficientType>
class TheComputation
{
public:
  List<Element<Integer>, Element<Integer>::HashFunction > theList;
};

int main()
{ TheComputation<Integer > A;
  Element<Integer> x;
  A.theList.GetHash(x);
  return 0;
}

//template class Element<Integer> ; 


Do an explicit instantiation of the class involved (uncomment line 47),
and it compiles and links cleanly.
compiles fine with clang++ 3.1, too.
Hey guys thanks for the feedback. If it does indeed compile with the clang and visual c++, it might indeed be a gcc issue.

Do you think it is worth it emailing the gcc team ?
[Edit:] I did report it in the gcc bugzilla anyways
Last edited on
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54235

The bug just got confirmed at the gcc bug tracker.

Cheers!
Topic archived. No new replies allowed.