Template function requires existence of inner class in non-templated class [duplicate] - c++

This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 6 years ago.
There's a template function f that requires its template parameter type T to have an inner class named Inner.
Inside f the class T::Inner shall be instantiated.
First try.
//
// "error: need 'typename' before 'T:: Inner' because 'T' is a dependent scope"
//
template <typename T>
void f( void )
{
T::Inner i;
}
I get that, so here comes the second try, where I don't get what's wrong:
/// "error: expected ';' before 'i'
template<typename T>
void f ( void )
{
typename T::Inner I;
I i;
}
Why is that?
In my understanding:
Inner is declared as type.
The template has not yet been instantiated.
Whether the type Inner exists or not first becomes relevant
on instantiation - not definition. Where am I going wrong?

I think you want to do
typename T::Inner i;
or
typedef typename T::Inner I;
I i;
whereas what you have in the question actually declares I to be a variable, and then right after that you are trying to use it as though it's a type.

Related

Is a typedef to self allowed over template parameters [duplicate]

This question already has answers here:
In a C++ template class, can I typedef the template parameter using the same name?
(2 answers)
Closed 1 year ago.
I was reading someone else's code when I came across this piece (stripped to MWE):
template<typename R> class Test {
public:
typedef R R;
};
Here there is a typedef of the template parameter to itself, and it made GCC and clang (with or without -std=c++2a) complain:
test.cc:3:19: error: declaration of 'typedef R Test::R' shadows template parameter
However, ICC and MSVC on Compiler Explorer both accept that piece.
I've read this question, and it is suggested that a typedef to self is usually a no-op. However, here it does not seem to be the case. I've also found this question to be related but I think they should be different since here we are using a typedef.
So here is the question:
Is this kind of redefinition allowed by the standard?
Are there any side effects of that statement? Why might one write that?
No. The name of a template parameter is not allowed to be redeclared.
The name of a template parameter is not allowed to be redeclared
within its scope (including nested scopes). A template parameter is
not allowed to have the same name as the template name.
template<class T, int N>
class Y {
int T; // error: template parameter redeclared
void f()
{
char T; // error: template parameter redeclared
}
};
template<class X> class X; // error: template parameter redeclared
From the standard, [temp.local]/6:
The name of a template-parameter shall not be bound to any following
declaration contained by the scope to which the template-parameter
belongs. [Example 5:
template<class T, int i> class Y {
int T; // error: template-parameter hidden
void f() {
char T; // error: template-parameter hidden
}
friend void T(); // OK: no name bound
};
template<class X> class X; // error: hidden by template-parameter
— end example]

Why does the standard library have a template<>? [duplicate]

This question already has answers here:
What is the meaning of template<> with empty angle brackets in C++?
(3 answers)
Closed 1 year ago.
I saw code in the standard library where the template was declared but the typename was not specified.
https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.2/cpp__type__traits_8h-source.html
00211 template<>
00212 struct __is_integer<int>
00213 {
00214 enum { __value = 1 };
00215 typedef __true_type __type;
00216 };
A name used in a template declaration or definition and that is dependent on a template-parameter is assumed not to name a type unless the applicable name lookup finds a type name or the name is qualified by the keyword typename.
source: Where and why do I have to put the "template" and "typename" keywords?
If this is the following, what is the use of this code? Why did they put in a template<> that you don't use?
Thanks to #Scheff, #chris.
This is a template specialization of a template <typename T> struct __is_integer;
https://www.cplusplus.com/doc/oldtutorial/templates/
https://en.cppreference.com/w/cpp/language/template_specialization
00147 //
00148 // Integer types
00149 //
00150 template<typename _Tp>
00151 struct __is_integer
00152 {
00153 enum { __value = 0 };
00154 typedef __false_type __type;
00155 };

Referencing a template from an inner class [duplicate]

This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 2 years ago.
I have the following code
template<typename VP,bool b>
class ValueProcessor{
template<typename Access,typename X> void processValue(X& x){}
};
template<typename VP>
class ValueProcessor<VP,true>{
public:
template<typename Access,typename X> void processValue(X& x);
};
template<typename VP>
template<typename Access,typename X>
void ValueProcessor<VP,true>::processValue(X& x){
class Updater{
ValueProcessor<VP,false> valPro;
X x;
public:
void operator()(){
valPro.processValue<Access,X>(x);
};
};
}
but it fails with this error
source>: In member function 'void ValueProcessor<VP, true>::processValue(X&)::Updater::operator()()':
<source>:23:32: error: expected primary-expression before ',' token
23 | valPro.processValue<Access,X>(x);
|
^
How can I refer to Access from the inner class?
As pointed out in the comment the solution is to add a .template discrimitaor before the member function name:
valPro.template processValue<Access,X>(x);
This is necessary because the type of ValueProcessor<VP,false> valPro is a dependent type (i.e. it's actual type depends on the type of the template parameter VP) the c++ language requires to add the .template disambiguator if you want to call a template member function of VP. Otherwise the parser would interpret the opening < as less-than operator.
See cppreference for a more in-depth discussion. The template disambiguator is described at the very end of that article.

Nested class in templated class used in templated function syntax error [duplicate]

This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 3 years ago.
Suppose I have the following:
template<typename T>
struct Foo
{
public:
class Bar
{
};
};
If I then define the function
template <typename T>
void func(Foo<T>::Bar g) { }
I get an error:
syntax error: identifier 'Bar'
Why do I get the error and how can I solve it so that I can use the templated function.
Use
template <typename T>
void func( typename Foo<T>::Bar g ) { }
Otherwise the construction Foo<T>::Bar is not considered by the compiler as a type specifier but as an expression.

Return a struct declared inside template class from a template method [duplicate]

This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 4 years ago.
I have the following:
#include <vector>
template <class T>
class A
{
public:
struct S
{
int a;
};
std::vector<S> returnStructs(void);
};
template <class T>
std::vector<A<T>::S> A<T>::returnStructs(void)
{
}
int main(void)
{
}
but when I try to compile I get:
error: template argument for template type parameter must be a type; did you forget
'typename'?
std::vector<A<T>::S> A<T>::returnStructs(void)
^
typename
so I switched out that line for:
std::vector<A<int>::S> A<T>::returnStructs(void)
^
'int' instead of 'T'
but then I get a new compiler error:
error: return type of out-of-line definition of 'A::returnStructs' differs from that in the
declaration
std::vector<A<int>::S> A<T>::returnStructs(void)
~~~~~~~~~~~~~~~~~~~~~~ ^
so any thoughts on how to fix this?
Also I realize I can just take struct S out of class A and be done with all these issues but I still feel like it should be possible to solve this without changing class A.
The first compiler error told you exactly what was wrong: did you forget 'typename'
As S is a member of a template you need to add typename to tell the compiler that it should delay the lookup of the name until after the template is resolved:
template <class T>
std::vector<typename A<T>::S> A<T>::returnStructs(void)