Overloading template class with template function - c++

C++ allows to use class and function with the same name in one namespace:
struct S {};
void S() {}
In this case pure name S means function S. To use struct instead you need to explicitly add struct before name.
It's also possible to make function template and still use both of them:
template <class T>
void S() {}
struct S {};
But using template struct is forbidden
void S() {}
template <class T>
struct S {};
and gives error like this:
error: redefinition of 'S' as different kind of symbol
What is the reason for this? Why not to allow use template struct here? Is there any situation where using explicit keyword struct before S (like for non-template version) could not solve name collision if it was allowed? Maybe there is proposal exist?

C++ allows to use class and function with the same name in one namespace.
struct S {};
void S() {}
Normally when you declare struct S, you can refer to the type in two ways: as S and as struct S. But that's only until you declare something else named S, for example, a function. When you do that, the name of the type is not S any more. It's struct S only. The name S is reserved for the function.
This is done for compatibility with C. C code uses this device frequently. Unlike C++, C places struct and union tags in a different name space from normal identifiers, and struct S cannot be referred to as simply S.
So C++, in order to be able to compile C code that uses this device, makes an exception for struct tags that are reused as a different kind of identifier.
As class is nearly synonymous with struct, this is done for the class keyword too.
But C has no templates and there's no need to provide backward compatibility for them, so no such exception for class templates is made.

I think function template name is allowed to be the same as something else to allow overloading, while class template name is explicitly disallowed to match something else according to
14 Templates [temp]
A class template shall not have the same name as any other template, class, function, variable, enumeration, enumerator, namespace, or type in the same scope (3.3), except as specified in (14.5.5).
[update] the rest of this piece makes me think that the case with function template not causing the same error violates the standard requirements:
Except that a function template can be overloaded either by non-template functions (8.3.5) with the same name or by other function templates with the same name (14.8.3), a template name declared in namespace scope or in class
scope shall be unique in that scope.
and VS / clang / gcc seem to disagree on it godbolt

Related

Visibility of members of base template class not directly inherited

The access to members of a template base class requires the syntax this->member or the using directive. Does this syntax extends also to base template classes which are not directly inherited?
Consider the following code:
template <bool X>
struct A {
int x;
};
template <bool X>
struct B : public A<X> {
using A<X>::x; // OK even if this is commented out
};
template <bool X>
struct C : public B<X> {
// using B<X>::x; // OK
using A<X>::x; // Why OK?
C() { x = 1; }
};
int main()
{
C<true> a;
return 0;
}
Since the declaration of the template class B contains using A<X>::x, naturally the derived template class C can access to x with a using B<X>::x. Nevertheless, on g++ 8.2.1 and clang++ 6.0.1 the above code compiles fine, where x is accessed in C with a using that picks up x directly from A
I would have expected that C can not access directly to A. Also, commenting out the using A<X>::x in B still makes the code to compile. Even the combination of commenting out using A<X>::x in B and at the same time employ in C using B<X>::x instead of using A<X>::x gives a code that compiles.
Is the code legal?
Addition
To be more clear: the question arises on template classes and it is about the visibility of members inherited by template classes.
By standard public inheritance, the public members of A are accessible to C, so using the syntax this->x in C one does indeed get access to A<X>::x. But what about the using directive? How does the compiler correctly resolve the using A<X>::x if A<X> is not a direct base of C?
You are using A<X> where a base class is expected.
[namespace.udecl]
3 In a using-declaration used as a member-declaration, each
using-declarator's nested-name-specifier shall name a base class of
the class being defined.
Since this appears where a class type is expected, it is known and assumed to be a type. And it is a type that is dependent on the template arguments, so it's not looked up immediately.
[temp.res]
9 When looking for the declaration of a name used in a template
definition, the usual lookup rules ([basic.lookup.unqual],
[basic.lookup.argdep]) are used for non-dependent names. The lookup of
names dependent on the template parameters is postponed until the
actual template argument is known ([temp.dep]).
So it's allowed on account of the compiler not being able to know any better. It will check the using declaration when the class is instantiated. Indeed, one can put any dependent type there:
template<bool> struct D{};
template <bool X>
struct C : public B<X> {
using D<X>::x;
C() { x = 1; }
};
This will not be checked until the value of X is known. Because B<X> can bring with it all sorts of surprises if it's specialized. One could for instance do this:
template<>
struct D<true> { char x; };
template<>
struct B<true> : D<true> {};
Making the above declaration be correct.
Is the code legal?
Yes. This is what public inheritance does.
Is it possible to allow a template class derived from B to access to x only via this->x, using B::x or B::x? ...
You can use private inheritance (i.e. struct B : private A<X>), and arrange access to A<X>::x only through B's public/protected interface.
Also, if you're worried about having hidden members, you should use class instead of struct and specify the desired visibility explicitly.
Regarding the addition, note that:
(1) the compiler knows what object A<X>::x refers to given some instance of A<X> (because A is defined in the global scope, and X is the template parameter of C).
(2) You do indeed have an instance of A<X> - this is a ponter to a derived class (it doesn't matter if A<X> is a direct base class or not).
(3) The object A<X>::x is visible in the current scope (because the inheritances and the object itself are public).
The using statement is merely syntactic sugar. Once all types are resolved, the compiler replaces following use of x with the appropriate memory address in the instance, not unlike writing this->x directly.
Maybe this example could give you some idea as to why should it be legal:
template <bool X>
struct A {
int x;
};
template <bool X>
struct B : public A<X> {
int x;
};
template <bool X>
struct C : public B<X> {
//it won't work without this
using A<X>::x;
//or
//using B<X>::x;
C() { x = 1; }
// or
//C() { this -> template x = 1; }
//C() { this -> x = 1; }
};
In case of choosing C() { this -> template x = 1; } the last inherited x (B::x) would be assigned to 1 not the A::x.
It can simply be tested by:
C<false> a;
std::cout << a.x <<std::endl;
std::cout << a.A::x <<std::endl;
std::cout << a.B::x <<std::endl;
Assuming that the programmer for struct B was not aware of struct A members, but the programmer of struct c was aware of members of both, it seems very reasonable for this feature to be allowed!
As to why should compiler be able to recognize using A<X>::x; when it is used in C<X> , consider the fact that within the definition of a class/class template all the direct/indirect inherited bases are visible regardless of the type of inheritance. But only the publicly inherited ones are accessible!
For example if it was like:
using A<true>::x;
//or
//using B<true>::x;
Then there would be a problem by doing:
C<false> a;
Or wise versa. since neither A<true> or B<true> is a base for C<false>, therefor visible. But since it is like:
using A<X>::x;
Because the generic term X is used in order to define the term A<X>, it is first deducible second recognizable, since any C<X> (if is not specialized later) is indirectly based on A<X> !
Good Luck!
template <bool X>
struct C : public B<X> {
// using B<X>::x; // OK
using A<X>::x; // Why OK?
C() { x = 1; }
};
The question is why wouldn't that be supported? Because the constrain that A<X> is a base of a specialization of the main template definition of C is a question that can only be answered, and that only makes sense for a particular template argument X?
To be able to check templates at definition time was never a design goal of C++. Many well formed-ness constrains are checked at instanciation time and this is fine.
[Without a true concept (necessary and sufficient template parameter contracts) support no variant of C++ would do significantly better, and C++ is probably too complicated and irregular to have true concepts and true separate checking of templates, ever.]
The principles that makes it necessary to qualify a name to make it dependent does not have anything with early diagnostic of errors in template code; the way name lookup works in template was considered necessary by the designers to support "sane" (actually slightly less insane) name lookup in template code: a use of a non local name in a template shouldn't bind too often to a name declared by the client code, as it would break encapsulation and locality.
Note that for any unqualified dependent name you can end up accidentally calling an unrelated clashing user function if it's a better match for overloading resolution, which is another problem that would be fixed by true concept contracts.
Consider this "system" (i.e. not part of current project) header:
// useful_lib.hh _________________
#include <basic_tool.hh>
namespace useful_lib {
template <typename T>
void foo(T x) { ... }
template <typename T>
void bar(T x) {
...foo(x)... // intends to call useful_lib::foo(T)
// or basic_tool::foo(T) for specific T
}
} // useful_lib
And that project code:
// user_type.hh _________________
struct UserType {};
// use_bar1.cc _________________
#include <useful_lib.hh>
#include "user_type.hh"
void foo(UserType); // unrelated with basic_tool::foo
void use_bar1() {
bar(UserType());
}
// use_bar2.cc _________________
#include <useful_lib.hh>
#include "user_type.hh"
void use_bar2() {
bar(UserType()); // ends up calling basic_tool::foo(UserType)
}
void foo(UserType) {}
I think that code is pretty realistic and reasonable; see if you can see the very serious and non local issue (an issue that can only be found by reading two or more distinct functions).
The issue is caused by the use of an unqualified dependent name in a library template code with a name that isn't documented (intuitivement shouldn't have to be) or that is documented but that the user wasn't interested in, as he never needed to override that part of the library behavior.
void use_bar1() {
bar(UserType()); // ends up calling ::foo(UserType)
}
That wasn't intended and the user function might have a completely different behavior and fails at runtime. Of course it could also have an incompatible return type and fail for that reason (if the library function returned a value unlike in that example, obviously). Or it could create an ambiguity during overload resolution (more involved case possible if the function takes multiple arguments and both library and user functions are templates).
If this wasn't bad enough, now consider linking use_bar1.cc and use_bar2.cc; now we have two uses of the same template function in different contexts, leading to different expansions (in macro-speak, as templates are only slightly better than glorified macros); unlike preprocessor macros, you are not allowed to do that as the same concrete function bar(UserType) is being defined in two different ways by two translation units: this is an ODR violation, the program is ill formed no diagnostic required. That means that if the implementation doesn't catch the error at link time (and very few do), the behavior at runtime is undefined from start: no run of the program has defined behavior.
If you are interested, the design of name lookup in template, in the era of the "ARM" (Annotated C++ Reference Manual), long before ISO standardization, is discussed in D&E (Design and Evolution of C++).
Such unintentional binding of a name was avoided at least with qualified names and non dependent names. You can't reproduce that issue with a non dependent unqualified names:
namespace useful_lib {
template <typename T>
void foo(T x) { ... }
template <typename T>
void bar(T x) {
...foo(1)... // intends to call useful_lib::foo<int>(int)
}
} // useful_lib
Here the name binding is done such that no better overload match (that is no match by a non template function) can "beat" the specialization useful_lib::foo<int> because the name is bound in the context of the template function definition, and also because useful_lib::foo hides any outside name.
Note that without the useful_lib namespace, another foo that happened to be declared in another header included before could still be found:
// some_lib.hh _________________
template <typename T>
void foo(T x) { }
template <typename T>
void bar(T x) {
...foo(1)... // intends to call ::foo<int>(int)
}
// some_other_lib.hh _________________
void foo(int);
// user1.cc _________________
#include <some_lib.hh>
#include <some_other_lib.hh>
void user1() {
bar(1L);
}
// user2.cc _________________
#include <some_other_lib.hh>
#include <some_lib.hh>
void user2() {
bar(2L);
}
You can see that the only declarative difference between the TUs is the order of inclusion of headers:
user1 causes the instanciation of bar<long> defined without foo(int) visible and name lookup of foo only finds the template <typename T> foo(T) signature so binding is obviously done to that function template;
user2 causes the instanciation of bar<long> defined with foo(int) visible so name lookup finds both foo and the non template one is a better match; the intuitive rule of overloading is that anything (function template or regular function) that can match less argument lists wins: foo(int) can only match exactly an int while template <typename T> foo(T) can match anything (that can be copied).
So again the linking of both TUs causes an ODR violation; the most likely practical behavior is that which function is included in the executable is unpredictable, but an optimizing compiler might assume that the call in user1() does not call foo(int) and generate a non inline call to bar<long> that happens to be the second instanciation that ends up calling foo(int), which might cause incorrect code to be generated [assume foo(int) could only recurse through user1() and the compiler sees it doesn't recurse and compile it such that recursion is broken (this can be the case if there is a modified static variable in that function and the compiler moves modifications across function calls to fold successive modifications)].
This shows that templates are horribly weak and brittle and should be used with extreme care.
But in your case, there is no such name binding issue, as in that context a using declaration can only name a (direct or indirect) base class. It doesn't matter that the compiler cannot know at definition time whether it's a direct or indirect base or an error; it will check that in due time.
While early diagnostic of inherently erroneous code is permitted (because sizeof(T()) is exactly the same as sizeof(T), the declared type of s is illegal in any instantiation):
template <typename T>
void foo() { // template definition is ill formed
int s[sizeof(T) - sizeof(T())]; // ill formed
}
diagnosing that at template definition time is not practically important and not required for conforming compilers (and I don't believe compiler writers try to do it).
Diagnostic only at the point of instantiation of issues that are guaranteed to be caught at that point is fine; it does not break any design goal of C++.

Why is using base class definitions in non-deduced context not permitted, and how to get around this?

I have the following code:
#include <iostream>
template <typename T>
struct Base
{
using Type = int;
};
template <typename T>
struct Derived : Base<T>
{
//uncommmenting the below cause compiler error
//using Alias = Type;
};
int main()
{
Derived<void>::Type b = 1;
std::cout << b << std::endl;
return 0;
}
Now the typename Type is available to Derived if its in a deduced context - as shown by the perfectly valid declaration of b. However, if I try to refer to Type inside the declaration of Derived itself, then I get a compiler error telling me that Type does not name a type (for example if the definition of Alias is uncommented).
I guess this is something to do with the compiler not being able to check whether or not Type can be pulled in from the base class when it is parsing the definition of Derived outside the context of a specific instantiation of parameter T. In this case, this is frustrating, as Base always defines Type irrespective of T. So my question is twofold:
1). Why on Earth does this happen? By this I mean why does the compiler bother parsing Derived at all outside of an instantiation context (I guess non-deduced context), when not doing so would avoid these 'bogus' compiler errors? Perhaps there is a good reason for this. What is the rule in the standard that states this must happen?
2). What is a good workaround for precisely this type of problem? I have a real-life case where I need to use base class types in the definition of a derived class, but am prevented from doing so by this problem. I guess I'm looking for some kind of 'hide behind non-deduced context' solution, where I prevent this compiler 'first-pass' by putting required definitions/typedefs behind templated classes or something along those lines.
EDIT: As some answers below point out, I can use using Alias = typename Base<T>::Type. I should have said from the outset, I'm aware this works. However, its not entirely satisfactory for two reasons: 1) It doesn't use the inheritance hierarchy at all (Derived would not have to be derived from Base for this to work), and I'm precisely trying to use types defined in my base class hierarchy and 2) The real-life case actually has several layers of inheritance. If I wanted to pull in something from several layers up this becomes really quite ugly (I either need to refer to a non-direct ancestor, or else repeat the using at every layer until I reach the one I need it at)
Because type is in a "dependent scope" you can access it like this:
typename Base<T>::Type
Your Alias should then be defined like this:
using Alias = typename Base<T>::Type;
Note that the compiler doesn't, at this point, know if Base<T>::type describes a member variable or a nested type, that is why the keyword typename is required.
Layers
You do not need to repeat the definition at every layer, here is an example, link:
template <typename T>
struct intermediate : Base<T>
{
// using Type = typename Base<T>::Type; // Not needed
};
template <typename T>
struct Derived : intermediate<T>
{
using Type = typename intermediate<T>::Type;
};
Update
You could also use the class it self, this relies on using an unknown specializations.
template <typename T>
struct Derived : Base<T>
{
using Type = typename Derived::Type; // <T> not required here.
};
The problem is that Base<T> is a dependent base class, and there may be specializations for it in which Type is not anymore defined. Say for example you have a specialization like
template<>
class Base<int>
{}; // there's no more Type here
The compiler cannot know this in advance (technically it cannot know until the instantiation of the template), especially if the specialization is defined in a different translation unit. So, the language designers chose to take the easy route: whenever you refer to something that's dependent, you need to explicitly specifify this, like in your case
using Alias = typename Base<T>::Type;
I guess this is something to do with the compiler not being able to check whether or not Type can be pulled in from the base class when it is parsing the definition of Derived outside the context of a specific instantiation of parameter T.
Yes.
In this case, this is frustrating, as Base always defines Type irrespective of T.
Yes.
But in general it would be entirely infeasible to detect whether this were true, and extremely confusing if the semantics of the language changed when it were true.
Perhaps there is a good reason for this.
C++ is a general-purpose programming language, not an optimised-for-the-program-Smeeheey-is-working-on-today programming language. :)
What is the rule in the standard that states this must happen?
It's this:
[C++14: 14.6.2/3]: In the definition of a class or class template, if a base class depends on a template-parameter, the base class scope is not examined during unqualified name lookup either at the point of definition of the class template or member or during an instantiation of the class template or member. [..]
What is a good workaround for precisely this type of problem?
You already know — qualification:
using Alias = typename Base<T>::Type;
When defining a template, sometimes things need to be a bit more explicit:
using Alias = typename Base<T>::Type;
Rougly speaking: a template is a blueprint of sorts. Nothing actually exists until the template get instantiated.
When doing the same thing, but in a non-template context, a C++ compiler will try to figure out what Type is. It'll try to find it in the base classes, and go from there. Because everything is already declared, and things are pretty much cut-and-dry.
Here, a base class does not really exist until the template gets instantiated. If you already know about template specialization, that you should realize that the base class may not actually turn out to have a Type member, when the template gets instantiated if there's a specialization for the base class defined later down the road, that's going to override the whole thing, and turn it inside and out.
As such, when encountering just a plain, old, Type in this context, the compiler can't make a lot of assumptions. It can't assume that it can look in any defined template base classes because those base classes may not actually look anything like the compiler thinks they will look, when things start to solidify; so you have spell everything out, explicitly, for the compiler, and tell the compiler exactly what your are trying to do, here.
You cannot use your base class types in a non-deduced context. C++ refuses to assume unbound names refer to things in your base class.
template <typename T>
struct Base {
using Type = int;
};
template<>
struct Base<int> {};
using Type=std::string;
template <typename T>
struct Derived : Base<T> {
using Alias = Type;
};
Now let us look at what is going on here. Type is visible in Derived -- a global one. Should Derived use that or not?
Under the rule of "parse nothing until instantiated", we use the global Type if and only if T is int, due to the Base specialization that removes Type from it.
Following that rule we run into the problem that we can diagnose basically no errors in the template prior to it being instantiated, because the base class could replace the meaning of almost anything! Call abs? Could be a member of the parent! Mention a type? Could be from the parent!
That would force templates to basically be macros; no meaningful parsing could be done prior to instantiating them. Minor typos could result in massively different behavior. Almost any incorrectness in a template would be impossible to diagnose without creating test instances.
Having templates that can be checked for correctness means that when you want to use your parent class types and members, you have to say you are doing so.
As a partial response about the point
[T]his is frustrating, as Base always defines Type irrespective of T.
I'd say: no it does not.
Please consider the following example differing from yours only by the one line definition of Base<void> and of the definition of Alias:
#include <iostream>
template <typename T>
struct Base
{
using Type = int;
};
template <typename T>
struct Derived : Base<T>
{
using Alias = typename Base<T>::Type; // error: no type named 'Type' in 'struct Base<void>'
};
template<> struct Base<void> {};
int main()
{
Derived<void>::Type b = 1;
std::cout << b << std::endl;
return 0;
}
In the context of template <typename T> struct Derived : Base<T>, there is no guaranty that Type exists. You must explicitly tell your compiler than Base<T>::Type is a type (with typename) and if you ever fail this contract, you'll end up with a compilation error.

Are "using typename" directives not implemented by compilers?

I have some code which looks like this:
namespace myLibrary
{
class A
{
public:
struct Nested
{
...
};
...
};
}
In some other parts of the code, I need to access A. Since I like readable code, I also like the using directive:
using myLibrary::A;
...
A a;
Now, at some point I also need to access my nested class, so I want to write something like this:
using myLibrary::A::Nested;
Obviously, the compiler can't know that this is a nested class and not a class member, and gives me an error:
error : using declaration can not refer to class member
What I can't understand is why this does not solve the problem:
using typename myLibrary::A::Nested;
The compiler still gives me the exact same error!
Luckily, I have alternatives:
// Using a typedef
typedef myLibrary::A::Nested Nested;
// Using the new C++11 syntax for type aliasing
using Nested = myLibrary::A::Nested;
but I'd like to understand why the using typename directive did not work. Does it not do what I think it does? Or is it not implemented by compilers? If it is the latter, is there a reason for it?
There is no "using typename directive". There are using-directives and using-declarations.
You're not using any using-directives, and they aren't relevant to the question in any case (they name namespaces, and can't use the typename keyword).
When using-declarations happen to appear within class templates, and happen to name dependent types, they have to use the typename keyword just like anything else that happens to be in a template and happens to name a dependent type.
For example:
template <typename A, typename R>
class Functor : public std::unary_function<A, R>
{
using typename std::unary_function<A, R>::result_type;
using typename std::unary_function<A, R>::argument_type;
public:
result_type operator() (argument_type) {}
};
In your situations, the namespace-declaration does not appear to be a part of the body of a class template, in fact it appears to be at namespace scope, in which case attempting to name a class member (doesn't matter if it's a type or a function or whatever) violates 7.3.3[namespace.udecl]/8
A using-declaration for a class member shall be a member-declaration
as the compiler correctly diagnosed with "error : using declaration can not refer to class member"
A using declaration referring to a namespace member A may only appear at namespace or local scope.
A using declaration referring to a class member Nested may only appear at class scope (along with member declarations), in a class derived from Nested. In fact, such using declarations are grammatically considered to be member declarations. They are used to adjust access qualification, and (with typename) to allow members of type-dependent bases to be used without qualification. These are specific use cases, so member using declarations are a bit specialized.
A nested class is a member of its enclosing class. You should generally avoid using class enclosures as a substitute for namespaces. Metaprogramming provides some exceptions to the rule, but in those cases you still wouldn't use using declarations, at least at namespace scope, because namespaces cannot be templated. Inheriting from an empty metaprogramming class is viable, but do mind the spaghetti.
The using directive is a different beast. It looks like using namespace and it links one namespace to another as a fallback path in name lookup.

Why does the compiler ignore struct elements inside a template class?

I am using g++ compiler. I wrote the following code which has a template class definition. The class has a struct data-type called node which has elements a and b of the generic type. The class has one function called print which prints p.h where p is a variable of type node of the class object. The compiler does not show any errors although 'h' is not an element of struct node. Why is that?
#include<iostream>
#include<cstdlib>
using namespace std;
template <typename e>
class mc
{
typedef struct node
{
e a,b;
}node;
node p;
public:
void print();
};
template <typename e>
void mc<e>::print()
{
std::cout<<p.h;
}
int main()
{
mc<int> m;
//m.print();
return(0);
}
The compiler shows an error only when m.print() is uncommented in main. Why is that?
If you donot use the object (instance) of a template, compiler only check the logic of the template. The template will not be instantiated. But if you try to use a instance of a template, that template will be instantiated (expanded) then you will see the error that h is not a member of p.
That is to say that , if you comment out //m.print(), the template will be instantiated.
In order to make writing template classes a bit easier, non-invoked template methods are not instantiated.
A few things are checked -- the signature of the method, and it does lookup of any methods or functions that involve only data non-dependent on the template parameters of the class and the like.
In this case, p is technically dependent on the template parameters of the class, so the check that p.h is valid is done at instantiation. Now, you could prove that there is no e such that p.h is valid, but the compiler doesn't have to, so it doesn't bother.
The program may still be ill-formed: there are clauses in the standard where programs can be ill-formed (no diagnostic required) if there are no valid specializations of a template, but I do not know if that applies to a method of a template or not.
Once you invoke print, the method is instantiated, and the error is noticed.
An example of where this is used in the std library is vector -- a number of its methods, including <, blinding invoke < on its data. vector does not require that its data support <, but it does require it if anyone tries to call <.
Modern C++ techniques would involve disabling vector::operator< in that case (the standard talks about "does not participate in overload resolution"), and in C++1z this becomes far easier via requires clauses (if that proposal ever gets standardized).

Default template argument for functions of classes : where to specify it?

Where do I have to specify default template parameters of classes member functions (assuming that the declaration is (of course) in the "class body", and the function definition is outside the class body) for each case in C++2011 :
"normal" functions
static functions
friend functions
In the definition, in the declaration or both ?
Well,
From my experiences creating template classes and methods, you specify a template function as such:
template<typename T>
T MyFunc(T &aArg1, T &aArg2)
{
//...Definition Goes Here
}
The typename T is the template argument type for the template function and you need to pass that data type consistently to each argument labeled as "T". This means that aArg2 has to be whatever data type aArg1 is. Now, when you call this function, you call it like so:
MyFunc</*datatype*/int>(iArg1, iArg2); the two arguments have to be data type "int" or you'll get a warning or an error.
Now, this also applies to class methods (I think that is what you meant by "classes member functions") which are the functions supplied by the class (i.e. MyClass::MyFunc()) so when you declare a class method that is a template method, you do it in the same manner. Here is an example class:
class MyClass
{
MyClass();
~MyClass();
template<typename T>
static T MyStaticFunc(T aArg) { return aArg; }
template<typename T>
T MyFunc(T aArg) { return aArg; }
}
As you can see, not to difficult. Now, static functions are the same way you just have to be sure t define then in the same module that the class is built in, otherwise, you'll get an error.
Unfortunately, I never really use "friend" methods, so I don't know how to tackle that. I would suspect you would do it in the same way as the other two. I hoped that whole essay of an answer helped.
Trying these out in Clang suggests the following:
For non-static and static functions, specifying the default in either the definition or
the declaration is acceptable - but not both and certainly not if
they contradict one another;
For friend functions, specifying a
default inside the class definition results in an error.