Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is this declaration of a function in template class invalid?

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;
                           ^
  • Why can't I declare func in a template derived class, while in non-template class it's OK?
  • What exactly is "invalidly declared function type"? what is invalid here?
like image 570
Ruslan Avatar asked Sep 01 '15 13:09

Ruslan


People also ask

How do you declare a template function?

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.

How do you declare a template class?

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.

What Cannot be declared as template in C++?

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.

What does template <> mean in C ++?

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.


1 Answers

N3337 [dcl.fct]/10: A typedef 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.

like image 87
TartanLlama Avatar answered Nov 02 '22 22:11

TartanLlama