Friend explicit specialization of function template and ADL - templates

Why in the following the partial specialization is not selected by ADL?
template<class T>
void func1(T&){ // selected
...
}
namespace first{
template<class R>
struct foo{
friend void func1<>(foo<R>&){ // expected
cout << "foo.func1" <<endl;
}
};
}
foo<int> f;
func1(f);

Template parameters are unrelated with friend declarations. You'll need to carry them disambiguated in thefriend declaration:
template<class R>
struct foo{
template<typename U>
friend void func1<U>(foo<U>&){
cout << "foo.func1" <<endl; // cat();
}
};
Also for your case you should decide, if you want to put the friend definition inlined as above, or just provide a declaration:
template<class R>
struct foo{
template<typename U>
friend void ::func1<U>(foo<U>&);
};
The latter should match the friend template function in the global namespace explicitly, and specialization can be made as necessary:
template<>
void func1(int&){
// ...
}
template<>
void func1(std::string&){
// ...
}
// a.s.o.

You don't need to provide an specialization of func1. Just provide an overload:
namespace first {
template <class R>
struct foo {
friend void func1(foo& ){
std::cout << "foo.func1" << std::endl;
}
};
}
int i;
first::foo<int> f;
func(i); // calls ::func<int>
func1(f); // calls first::func1(first::foo<int>& );
Otherwise, you can friend a specizliation, but you can't define a specialization in the class body:
template <class R>
struct foo {
friend void func1<>(foo& ); // friends ::func1<foo<R> >
};

Related

explicit specialization in template class error

my problem is the following, I have a template object, and in this object a method also template, for which I want to make a specialization, only the compiler always returns an error: "a declaration of model containing a list of model parameters can not be followed by an explicit specialization declaration.
I would like to understand in this case if how to specialize the method, here is the code:
template<typename T>class Foo
{
public:
template<typename T2> Foo<T2> cast(void);
};
template<typename T> template<typename T2> Foo<T2> Foo<T>::cast(void)
{
Foo<T2> tmp;
std::cout << "1" << std::endl;
return tmp;
}
template<typename T> template<> Foo< int > Foo<T>::cast< int >(void)
{
Foo<int> tmp;
std::cout << "2" << std::endl;
return tmp;
}
int main()
{
Foo<double> bar();
bar.cast<int>();
}
The problem is that we can't fully specialize the member function template without also fully specializing the class template also. This means that the correct syntax would be as shown below:
template<typename T> struct CompressVector
{
template<typename T2> CompressVector<T2> cast();
};
template<typename T> template<typename T2> CompressVector<T2> CompressVector<T>::cast()
{
CompressVector<T2> tmp;
//other code here
return tmp;
}
//vvvvvvvvvv-vvvvvvvvv-------------------------------------vvv------------>made changes here
template<> template< > CompressVector<int> CompressVector<int>::cast< int >(void)
{
CompressVector<int> tmp;
//other code here
return tmp;
}
Working demo

C++11 providing empty non-member function when it is missing

In my serialization system, I can provide non-member functions that implement how to serialize given types:
// struct foo
struct foo {
int bar;
};
// serialize foo
template <class stream> void serialize(stream& s, foo& f) {
stream.serialize(f.bar);
}
If I wanted to provide an empty serialize implementation when a non-member function serialize does not exist for a given type, how can I achieve that using C++11?
I tried this
template <class stream, class type> void serialize(stream&, type&) {}
// struct foo
struct foo {
int bar;
};
// serialize foo
template <class stream> void serialize(stream& s, foo& f) {
stream.serialize(f.bar);
}
// ...later in source file:
foo f;
stream s;
serialize(s, f);
but it always calls the empty method somehow.
Add a non-member function template.
template <typename stream, typename T> void serialize(stream& s, T& t) {}
Here's a demonstrative program:
#include <iostream>
template <typename stream, typename type> void serialize(stream&, type&)
{
std::cout << "Came to 1\n";
}
struct stream
{
void serialize(int ) {}
};
// struct foo
struct foo {
int bar;
};
// serialize foo
template <class stream> void serialize(stream& s, foo& f) {
std::cout << "Came to 2\n";
s.serialize(f.bar);
}
struct bar {
};
int main()
{
// ...later in source file:
foo f;
stream s;
serialize(s, f);
bar b;
serialize(s, b);
}
and its output under cygwin/g++ 6.4.0:
Came to 2
Came to 1
It works at ideone.com too.

C++ template, static function specialization

I have a syntax error with my template
I would like to partial specialize a static function of my template class
class.hpp
template <typename Foo, size_t bar = 26>
class MyClass
{
MyClass();
static void function();
};
#include "class.tpp"
class.tpp
template <typename Foo, bar>
MyClass<Foo, bar>::MyClass()
{ }
template <typename Foo>
inline
void
MyClass<Foo, 6>::function()
{
// ...
}
template <typename Foo>
inline
void
MyClass<Foo, 26>::function()
{
// ...
}
error: template definition of non-template
I just want to implement MyClass<Foo, bar>::function for bar == 26 and bar == 6
How to do that properly ?
Thanks
The function is not a template itself, it is only inside a class template. You can specialize the class for those cases, but not the function itself.
template <class Foo>
class MyClass<Foo, 26>
{
static void function() { ... }
};
Provided you have specialized the class like so, you can only declare the function inside the class, and define it outside like so:
template <class Foo>
void MyClass<Foo, 26>::function() { ... }
If you don't specialize it beforehand, you'll get a compilation error for using an incomplete type.
You might also find this question and answer on specializing a single function inside a class template relevant.
You cannot partial specialize method like that.
You may partial specialize the whole class.
or as alternative, you may forward the implementation to some helper:
struct that you may specialize as you want.
overload (using some dispatching):
namespace detail
{
template <typename Foo, std::size_t bar>
void function_impl(MyClass<Foo, bar>& that)
{
// Generic case.
}
template <typename Foo>
void function_impl(MyClass<Foo, 6>& that)
{
// special case <Foo, 6>.
}
template <typename Foo>
void function_impl(MyClass<Foo, 26>& that)
{
// special case <Foo, 26>.
}
}
template <typename Foo, std::size_t bar>
inline
void
MyClass<Foo, bar>::function()
{
detail::function_impl(*this);
}
After doing some research; Partial Specialization for member functions of a class template are not allowed, so one would have to specialize the whole class which can be a problem if the actual class is quite large. If you are trying to separate the implementation from the declaration having a wrapper or helper will work, but you must defined that and the partial specialization first. Check out this code here for it compiles, builds and outputs the appropriate values using MSVC 2015 CE.
MyClass.h
#ifndef MY_CLASS_H
#define MY_CLASS_H
#include <iostream>
// Helper - Wrapper Class
template<typename Foo, size_t Bar>
class specialized {
public:
inline static void function();
};
// Partial Specialization
template<typename Foo>
class specialization<Foo, 6> {
public:
inline static void function();
};
// Actual Class
template<typename Foo, size_t Bar = 26>
class MyClass {
private:
specialized<Foo, Bar> func;
public:
MyClass();
inline void function(); // Works
// inline static void function(); // Compiler Error
}; // MyClass
#include "MyClass.inl"
#endif // MY_CLASS_H
MyClass.inl
// Helper - Wrapper
template<typename Foo, size_t Bar>
inline void specialized<Foo, Bar>::function() {
std::cout << "26" << std::endl;
} // function
// Specialized
template<typename Foo>
inline void specialized<Foo, 6>::function() {
std::cout << "6" << std::endl;
} // function
// Constructor
template<typename Foo, size_t Bar>
MyClass<Foo, Bar>::MyClass() {
} // MyClass
// Class Member Function
template<typename Foo, size_t Bar>
inline void MyClass<Foo, Bar>::function() {
func.function();
} // function
MyClass.cpp
#include "MyClass.h"
Main.cpp
#include "MyClass.h"
int main() {
MyClass<float, 6> a;
a.function(); // Prints Out 6
MyClass<float, 26> b;
b.function(); // Prints Out 26
MyClass<float> c;
c.function(); // Prints Out 26
MyClass<float, x != 6> d;
d.function(); // Prints Out 26
return 0;
} // Main

explicit instantiation after specialization

#include <iostream>
using namespace std;
template <typename>
class Test
{
void fun() { cout << "test" << endl; }
void bar() { cout << "bar"; }
};
template<>
class Test<int>
{
void fun(){}
};
template void Test<int>::fun();
I got an error:
error: template-id 'fun<>' for 'void Test::fun()' does not match any template declaration
But why?
I know it work if add template for fun in Test e.g.
template<>
class Test<int>
{
template <typename>
void fun(){}
};
template void Test<int>::fun<bool>();
For function template
template<class T> void sort(Array<T>& v) { /*...*/ } // primary template
template<> //explicit specialization of sort(Array<String>)
void sort<String>(Array<String>& v); // after implicit instantiation
template
void sort(Array<String>& v);// no matter before/after void f(Array<String>& v) , it both works
void f(Array<String>& v) {
sort(v); // implicitly instantiates sort(Array<String>&),
} // using the primary template for sort()
An explicit specialisation (that is, not a partial specialisation) is no longer a template. That means all of its members really exist (as if they were instantiated), so you cannot (and need not) instantiate them.

Template specific methods

If I have a class A
template <typename T>
class A { public: void print() const; };
I can write specific version of my methode print for specific template values my doing
template<> void A<bool>::print() const { printf("A w/ type bool\n"); }
template<> void A<int>::print() const { printf("A w/ type int\n"); }
and the calling the method print will just call the code of the good implementation (of the compiler tell me if I don't have an implementation for a specific template.
Now, if I have multiples types in my class B's template
template <typename T1, typename T2>
class B { public: void print() const; };
and if I try to do the same as before, let's say for T2
template<typename T1> void B<T1,bool>::print() const { printf("B w/ type bool\n"); }
I get an compiler error :
error: invalid use of incomplete type 'class B<T1,bool>'
error: declaration of 'class B<T1, bool>'
What am I doing wrong ?
EDIT
My real life B class contains other methods with I do not want to specify (they work in the general case)
Having a partially specified class decalred makes that those generic methods aren't natively availlable
You can't partial specialize a function/method.
But you can partial specialize the whole class:
template <typename T1, typename T2> class B;
template<typename T1> class B<T1, bool>
{
public:
void print() const { printf("B w/ type bool\n"); }
};
What am I doing wrong?
template<> void A<bool>::print() const { printf("A w/ type bool\n"); }
template<> void A<int>::print() const { printf("A w/ type int\n"); }
These member functions are like normal functions, they are not templates with un-substituted parameters, so you are just providing definitions for the symbols, which will be used when those functions get called. (And like normal functions, if those definitions are in a header and you don't declare them inline you will get multiple definitions errors for them.)
template<typename T1> void B<T1,bool>::print() const { printf("B w/ type bool\n"); }
This is not the same, this is providing a definition for a member function of a class template partial specialization. i.e. it's a template that will be used to generate code for the member of that partial specialization, but you haven't declared any such partial specialization, so you can't define its members.
You can make it compile by defining the partial specialization first:
// primary template
template <typename T1, typename T2>
class B { public: void print() const; };
// partial specialization
template<typename T1>
class B<T1,bool> { public: void print() const; };
template<typename T1> void B<T1,bool>::print() const { printf("B w/ type bool\n"); }
However it is often inconvenient to have to repeat the entire class template definition just to define a partial specialization for one or two members, so it might be worth taking one of the alternative designs shown in other answers.
With templates it's best to decompose each part of the specialisation into its own template function or traits class.
Here's a clean way to do what you want:
template<typename T>
const char* type_name()
{
return "unknown";
};
template<>
const char* type_name<int>()
{
return "int";
}
template<>
const char* type_name<bool>()
{
return "bool";
}
struct foo {};
template<>
const char* type_name<foo>()
{
return "my custom foo";
}
struct bar {};
template <typename T>
class A {
public:
void print() const {
cout << "A w/ type " << type_name<T>() << '\n';
}
};
int main() {
A<bool> ab;
A<int> ai;
A<foo> af;
A<bar> abar;
ab.print();
ai.print();
af.print();
abar.print();
return 0;
}
output:
A w/ type bool
A w/ type int
A w/ type my custom foo
A w/ type unknown
Program ended with exit code: 0
With tag dispatching, you might do:
#include <iostream>
template<typename A, typename B>
class X
{
private:
template <typename U> struct Tag {};
template <typename U>
void print(Tag<U>) const;
void print(Tag<bool>) const { std::cout << "bool\n"; }
void print(Tag<int>) const{ std::cout << "int\n"; }
public:
void print() const { print(Tag<B>()); }
};
int main()
{
X<void, bool>().print();
X<void, int>().print();
}