2

I have a metafunction:

struct METAFUNCION
{
  template<class T>
  struct apply
  {
    typedef T type;
  };
};

Then I define a helper:

template<class T1, class T2>
struct HELPER
{
};

And then I have second metafunction which derives from the METAFUNCTION above and defines partial specialization of apply struct:

struct METAFUNCION2 : METAFUNCION
{
  template<class T1, class T2>
  struct apply<HELPER<T1, T2> > : METAFUNCION::apply<T2>
  {
  };
};

So far, so good - the code compiles under g++ 4.3.2. So I used it like below:

#include <typeinfo>
#include <string>
#include <cstdlib>
#include <cxxabi.h>

template<typename T>
struct type_info2
{
  static std::string name()
  {
    char *p = abi::__cxa_demangle(typeid(T).name(), 0, 0, 0);
    std::string r(p);
    free(p);
    return(r);
  }
};

#include <boost/mpl/apply.hpp>
#include <iostream>

int main()
{
  std::cout <<
    type_info2<boost::mpl::apply<METAFUNCION, int>::type>::name() <<
    std::endl;
  std::cout <<
    type_info2<boost::mpl::apply<METAFUNCION, HELPER<float, double> >::type>::name() <<
    std::endl;
  std::cout <<
    type_info2<boost::mpl::apply<METAFUNCION2, HELPER<float, double> >::type>::name() <<
    std::endl;
  return(0);
}

The output:

int
double
double

That surprised me a bit as I expected:

int
HELPER<float, double>
double

Now, I know that code like above does not compile under Microsoft Visual C++ 2008 (I don't remeber the message but it was something along the lines that I cannot specialize apply struct inside METAFUNCTION2 struct).

So my question is - is this g++ behaviour conformant with the standard? I have a strong feeling that there is something wrong here but I am not 100% sure.


For the curious - I have the behaviuor as I expected when I redefine METAFUNCTION2 this way:

struct METAFUNCION2 : METAFUNCION
{
  template<class T>
  struct apply : METAFUNCION::apply<T>
  {
  };
  template<class T1, class T2>
  struct apply<HELPER<T1, T2> > : METAFUNCION::apply<T2>
  {
  };
};
Tomek
  • 4,554
  • 1
  • 19
  • 19
  • 3
    This isn't your real code, since `template struct apply > : METAFUNCION::apply {};` wouldn't compile. I stopped reading your question there. – sbi Sep 11 '09 at 20:47
  • It's a pity you haven't specified which compiler and version you used. I've made it perfectly clear that the code DOES compile on g++ 4.3.2 and DOES NOT compile on VC++ 2008. – Tomek Sep 12 '09 at 18:51
  • @Tomek: I used Brain 1.0. `:)` The code was simply wrong. I'm sorry for dismissing your question too early, but there's so much erroneous code pasted into questions here, that I made it a habit to stop bothering when the errors are at the heart of the question. I can't believe, gcc4 would get this wrong... – sbi Sep 12 '09 at 22:13
  • As far as i understand the question, he didn't claim the code was right, though. He asked which compiler is right. I've made that kind of question too. I tested with gcc4.4, and yes it gets it wrong (at least, different than comeau, which says a lot in itself haha). – Johannes Schaub - litb Sep 13 '09 at 14:07
  • 1
    @lib: He wrote "the code compiles under g++ 4.3.2". I didn't believe that. I was wrong. That's why I said I'm sorry. – sbi Sep 13 '09 at 19:21

2 Answers2

3

So I filed a bug on gcc

Tomek
  • 4,554
  • 1
  • 19
  • 19
  • I believe your Standard quote doesn't apply though, because you are not declaring an explicit specialization (you are declaring and defining a partial specialization instead), and because the declaration of the class template being specialized *is* in scope already. I haven't found a clearly spelled out requirement that the partial specialization of a member template should be a member of the same class, though. – Johannes Schaub - litb Sep 11 '09 at 23:37
  • Well, VC++ rejects the code so at least there is something to think about. And as I wrote - I wouldn't expect partial specialization to work up the inheritance tree. At least this is what I though when I "invented" that code. – Tomek Sep 12 '09 at 05:55
  • @Tomek, same suspicion here :) I neither think that partial specialization should work up the tree. Both the primary and the partial specialization templates are "alternative definitions" (original wording) for the same template, so they should provide definitions for the template in the same class scope, not in the derived class scope (which would mean the definition occurs for another scope than the declaration of the template). But i would have liked an explicit quote about that in the standard. – Johannes Schaub - litb Sep 12 '09 at 10:34
  • 1
    For the followers I've just got an email from gcc bugzilla that this bug is fixed in gcc 4.5.0. – Tomek Dec 27 '09 at 08:18
2

The following code is illegal:

struct METAFUNCION2 : METAFUNCION
{
  template<class T1, class T2>
  struct apply<HELPER<T1, T2> > : METAFUNCION::apply<T2>
  {
  };
};

According to C++ Standard 14.7.3/3:

A declaration of a function template or class template being explicitly specialized shall be in scope at the point of declaration of an explicit specialization.

EDIT: According to Core Issue 727 this restriction does not apply to partial specializations of member templates.

Kirill V. Lyadvinsky
  • 97,037
  • 24
  • 136
  • 212
  • Well it still is not clear if it should be possible to specialize inner template of base class in its derivative and if it should then be visible in derived class only or base class as well. – Tomek Sep 12 '09 at 18:55