Declaring template function friends involves some incredibly unintuitive syntax, even for C++! What is the rationale behind the choice of syntax for the extra <> needed? Wouldn't it make more sense to use the template keyword?
For those that don't know about this, here is an example of what you might try to do:
template <typename T>
class Foo
{
int x;
friend void bar(Foo<T>);
};
template <typename T>
void bar(Foo<T> f)
{
std::cout << f.x;
}
If you try to call bar(Foo<T>()), you will get linker errors.
To solve this, you have to forward declare bar (and therefore Foo) and then stick an oddly placed <> in the friend declaration.
template <typename T> class Foo;
template <typename T> void bar(Foo<T>);
template <typename T>
class Foo
{
int x;
friend void bar<>(Foo<T>); // note the <> (!?)
};
template <typename T>
void bar(Foo<T> f)
{
std::cout << f.x;
}
My question is, what is the rationale behind the <> syntax? Wouldn't it be more intuitive to use the template keyword or something along those lines?
EDIT: To clarify, I already know why the <> is required, what I want to know is why they chose to use <> to disambiguate it instead of some other more intuitive syntax.
Wait. You are not declare a friend template. You declare a specialization of a template as friend! As such, why would you want to put a template clause there?
The syntax to name specializations of function templates is by teplateName<ArgumentList>, and that is what you shall use according to the Standard in the friend declarations.
If you want to befriend the whole template and all specializations generated and explicitly specialized, you can still do that, and then you can use a template clause
template<typename U>
friend void bar(Foo<U>);
Quoting this page:
The non-template function is called because a non-template function takes precedence in overload resolution.
So my guess the friend void bar<>(Foo<T>); is intuitive because you want to make sure it's the template function you are calling and not an overload for Foo<T>. There would otherwise no way for the compiler to notice if the templated or the non-templated function is the class'es friend.
Why the <> syntax is used and not the template syntax is not clear to me.
Related
If I have a widely-used class template called Foo that I want to rename to Bar without having to update all of its users atomically, then up until C++17 I could simply use a type alias:
template <typename T>
class Bar {
public:
// Create a Bar from a T value.
explicit Bar(T value);
};
// An older name for this class, for compatibility with callers that haven't
// yet been updated.
template <typename T>
using Foo = Bar<T>;
This is very useful when working in a large, distributed codebase. However as of C++17 this seems to be broken by class template argument deduction guides. For example, if this line exists:
template <typename T>
explicit Foo(T) -> Foo<T>;
then the obvious thing to do when renaming the class is to change the Foos in the deduction guide to Bars:
template <typename T>
explicit Bar(T) -> Bar<T>;
But now the expression Foo(17) in a random caller, which used to be legal, is an error:
test.cc:42:21: error: alias template 'Foo' requires template arguments; argument deduction only allowed for class templates
static_cast<void>(Foo(17));
^
test.cc:34:1: note: template is declared here
using Foo = Bar<T>;
^
Is there any easy and general way to give a class with deduction guides two simultaneous names in a fully compatible way? The best I can think of is defining the class's public API twice under two names, with conversion operators, but this is far from easy and general.
Your problem is exactly what P1814R0: Wording for Class Template Argument Deduction for Alias Templates
wants to solve, that is to say, in C++20, you only need to add deduction guides for Bar to make the following program well-formed:
template <typename T>
class Bar {
public:
// Create a Bar from a T value.
explicit Bar(T value);
};
// An older name for this class, for compatibility with callers that haven't
// yet been updated.
template <typename T>
using Foo = Bar<T>;
template <typename T>
explicit Bar(T) -> Bar<T>;
int main() {
Bar bar(42);
Foo foo(42); // well-formed
}
Demo.
But since it is a C++20 feature, there is currently no solution in C++17.
Have you tried to define a macro?
#define Foo Bar;
(Personally I'd find it confusing with multiple names for same implementation, but I'm not you.)
Sorry I can't test at the moment, but I hope it works!
Given the following class
template <class T>
class A {
static const B<T> member;
};
how can I instantiate member for each class A<T> separately?
Simple. As you would with any other static non-integral type.
template <class T>
class A {
static const B<T> member;
};
template <class T>
const B<T> A<T>::member/*(optional-args)*/;
In order to allocate member differently for different types of T, you must use template specialisation.
To start the template specialisation you must use this syntax:
template<>
// ... explicit definition
The syntax for the explicit definition is basically the same syntax as:
template <class T>
const B<T> A<T>::member/*(optional-args)*/;
Except, instead of template <class T>, you use template<>, and where T is, you put the actual type.
For example:
template<>
const B<type> A<type>::member(args);
NOTE: If you wish to call the default constructor with template specialisation in this scenario, please see the EDIT below.
You can substitute type for any type you wish. With this you can provide different arguments for each possible type. Although if you specialise too much, you should consider if your design is really suited to use templates.
Here it is in action (online), feel free to clone and play around with it.
I thought I'd mention that the declaration must be where the template class is located. In other words, if A is declared in the header, you must also declare the allocation for member in the header file. You can alternatively use an inline file (.inl) and #include the .inl file in the header file that the template class is declared.
EDIT:
It seems that in C++98, the following syntax to call the default constructor does not compile under GCC or clang, if you refer to the member variable:
template <>
const B<type> A<type>::member/*()*/;
Where type is any type.
However the following does:
template <class T>
const B<T> A<T>::member/*()*/;
I'm not sure if this is a bug, or just incorrect syntax.
I recommend instead to do the following:
template <>
const B<type> A<type>::member = B<type>();
Or if you are using C++11, you can use curly brackets to call the default-constructor, like so:
template <>
const B<type> A<type>::member{};
If you use regular brackets, the compiler will thing it is a static function within the A<type> class, and if you use no brackets, you will get an undefined reference to 'A<type>::member' linker error. Which you can see here.
Here is the discussion that Aaron and I discovered this error.
What has the meaning the "using of template keyword in the function declaration"?
In this example compiler errors with error: "func" is not a template function.
template<typename T>
struct Window {
T value;
};
template void func(Window<int>, int);
template<typename T>
void func(Window<T>, T) {
}
int main(void) {
}
But below example is ok.
template<typename T>
struct Window {
T value;
};
template<typename T>
void func(Window<T>, T) {
}
template void func(Window<int>, int);
int main(void) {
}
What is the meaning with "template" in the above case?
Is it just indicator that this function is template function?
A declaration that begins with the keyword template and does not have the <pointy braces> immediately afterward is called an explicit instantiation. It means to look up the template definition and plug in the specified template parameters to get a specific function specialization or class specialization. So in the first example, the compiler is complaining it can't instantiate func(Window<int>, int) because it doesn't yet know anything about a template called func.
Explicit instantiations are usually not necessary, since templates can be implicitly instantiated just by attempting to use them. But explicit instantiation gives some control over where and how related linker symbols appear, and can in some cases be used to move a template definition out of a header file into a source file.
This is just because in your first example you have the definition of the template
template<typename T>
void func(Window<T>, T) {
}
after the forced instantiation that's represented by this line:
template void func(Window<int>, int);
Whereas in the second example they're the right way around.
But the comment to your question is fair, you are asking a basic question ('what does template mean'), which is best answered by a thoroughgoing study of the subject.
I am looking at some c++ code and do not understand the purpose of the template declaration in this situation:
template<> void operator>>(const ClassA& s, const ClassB d) {...}
What is the semantic of template<>?
This is, indeed, template specialization, as others before mentioned. There must be some previously declared function template, such as:
template<typename T, typename U>
void operator>>(const T& s, const U d) {...}
However, it is quite misguided. It is much better to remove the template<> altogether, so operator>> would just be overloaded. The problem with function template specialization is that it may lead to unexpected behaviour in the presence of overloaded functions (and operator>> has lots of overloads), since the specialization does not overload. This means that the compiler first selects the most appropriate overload for the function and then, if the selected overload is a function template, it looks for template specializations to see if there is an appropriate one.
A classical example (unfortunately, I don't remember where I read it). Consider this overloaded function template:
template <typename T>
void Function(T param);
template <typename T>
void Function(T* param);
template <>
void Function(int* param);
main()
{
int i = 5;
Function(&i);
}
As expected, the template specialization for int* is called. But just change the order of the function definitions:
template <typename T>
void Function(T param);
template <>
void Function(int* param);
template <typename T>
void Function(T* param);
main()
{
int i = 5;
Function(&i);
}
Now the general template for T* is called, since we are specializing the template for T, not for T*, and this second template is better suited for our call. This would be avoided if we overloaded the function instead of specializing the template:
void Function(int* param);
Now the order of declaration does not matter, we will always call the overload for int*.
UPDATE: Now I know who to credit. I read about this in an article by Herb Sutter. The example was provided by Peter Dimov and Dave Abrahams.
This is Template specialization
You use this syntax when you want to provide a special handler for a particular template type. Consider:
// A normal template definition.
template <typename AType>
whoami () { std::cout << "I am an unknown type."; }
// Now we specialize.
template <>
whoami<int> () { std::cout << "I am an integer!"; }
There's some other nonsense involved, particularly "partial specialization", but that's the basic function of template <>.
It is a template specialization: (fully or partially) resolving the template for a specific type. (Your particular example seems to be a full specialization, as no more template parameters are left unresolved in it. If the template has multiple parameters, and you specialize only some of them, it is called partial template specialization)
This allows one to provide type-specific optimizations for a given template, or to do many clever tricks such as detecting the static type of variables etc.
I know this subject should be pretty much dated by now, but I'm having a tough time with this specific case.
Straight to the point, this is what I want to do:
enum MyEnum
{
E_1,
E_2
};
template <MyEnum T>
class MyClass
{
// method to be fully specialized
template <typename U>
void myMethod(U value);
};
// full specialization of method template from class template
// (or is this in fact partial, since I'm leaving T alone?)
template <MyEnum T>
template <>
void MyClass<T>::myMethod<int>(int value)
{
std::cout << value << '\n';
}
Is this possible?
C++03 [$14.7.3/18] says
In an explicit specialization declaration for a member of a class template or a member template that appears in namespace scope, the member template and some of its enclosing class templates may remain unspecialized, except that the declaration shall not explicitly specialize a class member template if its enclosing class templates are not explicitly specialized as well.
So you need to specialize the enclosing class too.
Something like this would work.
template <>
template <>
void MyClass<E_1>::myMethod<int>(int value)
{
std::cout << value << '\n';
}
Since you leave T, while specializing only function template, then what you're trying to do would be called partial specialization, because T is still templated and you can use it in your function. But unfortunately, partial template specialization of function (whether be it member function or non-member function) is not allowed. So your code would give compilation error.
Either you fully specialize by specializing the class template as well, or you don't at all.