Consider the following code:
template<int X, int Y>
struct S
{
typedef int func(int,float) const;
};
template<int X>
struct D : public S<X,6>
{
typename S<X,6>::func func;
};
template<int X>
int D<X>::func(int,float) const
{
return 1;
}
//----------------
struct W : public S<7,8>
{
S<7,8>::func func;
};
int W::func(int,float) const
{
return 2;
}
#include <iostream>
int main()
{
W w;
std::cout << w.func(1,4.3) << "\n";
D<3> d;
std::cout << d.func(1,4.3) << "\n";
}
If I comment out the code declaring class D
and D::func()
as well as the corresponding lines in main()
, the code compiles normally, and I see 2
in output, as expected.
But when I make the derived class template (adding typename
before function declaration, as S<X.6>
is a dependent scope), I get the following errors:
test.cpp:13:27: error: no ‘int D<X>::func(int, float) const’ member function declared in class ‘D<X>’
int D<X>::func(int,float) const
^
test.cpp: In instantiation of ‘struct D<3>’:
test.cpp:32:10: required from here
test.cpp:10:27: error: field ‘D<3>::func’ invalidly declared function type
typename S<X,6>::func func;
^
func
in a template derived class, while in non-template class it's OK?To instantiate a template function explicitly, follow the template keyword by a declaration (not definition) for the function, with the function identifier followed by the template arguments. template float twice<float>( float original ); Template arguments may be omitted when the compiler can infer them.
To instantiate a template class explicitly, follow the template keyword by a declaration (not definition) for the class, with the class identifier followed by the template arguments. template class Array<char>; template class String<19>; When you explicitly instantiate a class, all of its members are also instantiated.
Which of the following cannot be declared as template ? Correct Answer : OPTION D, Macros. Macros are implemented in a preprocessor and cannot be implemented as a template. Functions and classes can be declared as templates.
Templates are a feature of the C++ programming language that allows functions and classes to operate with generic types. This allows a function or class to work on many different data types without being rewritten for each one.
N3337 [dcl.fct]/10:
Atypedef
of function type may be used to declare a function but shall not be used to define a function.
By this rule, both D
and W
are technically well-formed. I think the reason this doesn't compile with GCC or Clang is that declaring a function with a typedef is really rare. Declaring a function with a member typedef dependent on a template parameter is even rarer. Looks like you've just hit on a dark corner where compiler support is limited.
Funnily enough, MSVC actually does the right thing here.
Your best option is probably to find a different way to express your classes. I can't really give any directed advice without knowing more about the problem you are trying to solve, but if you ask a new question with details we can give some suggestions.
You might also think about filing a bug report for GCC and Clang.
Edit:
However, as Jarod42 pointed out, the dependent type could later be defined as something other than a function type, making the declaration invalid. The reason MSVC works where GCC and Clang does not is the same reason MSVC doesn't require typename
in some places: it doesn't correctly implement two-phase lookup. Having this case fully specified would require something like function_typename
to mark a dependent name as being a function type. I think declaring a function based on a dependent type is underspecified and inconsistent as a result of this being a very rare case.
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