Can someone please explain me why is this not compiling...the specialized function of a specialized class ???
In the specialized version of the templated class the specialized function is not compiling.
#include<iostream>
using namespace std;
//Default template class
template<typename T>
class X
{
public:
void func(T t) const;
};
template<typename T>
void X<T>::func(T b) const
{
cout << endl << "Default Version" << endl;
}
//Specialized version
template<>
class X<int>
{
public:
void func(int y) const;
};
template<>
void X<int>::func(int y)
{
cout << endl << "Int Version" << endl;
}
int main()
{
return 0;
}
An explicit specialization of a class template is a concrete class, not a template, so you can (or rather, should) just write:
// template<>
// ^^^^^^^^^^
// You should not write this
void X<int>::func(int y) const
// ^^^^^
// And do not forget this!
{
cout << endl << "Int Version" << endl;
}
Thus leaving out the template<> part.
Also, mind the fact that your func() function is const-qualified in the declaration - so you have to use the const qualifier even in the defintion.
Here is a live example.
I think you left off the trailing const modifier
Related
In C++ I want to specialize a templated function. So far so good.
The problem is that the type that specialize my template depends on a typedef to which I don't have access.
Purpose explication
The user must first define a typedef for the class Surface_mesh by specifying some types in the template.
typedef CGAL::Surface_mesh<CGAL::Simple_cartesian<double>::Point_3> Mesh;
Mesh may vary according to the user's needs, but it will always have the following typedef:
Mesh::Face_index
Mesh::Vertex_index
Mesh::Edge_index
Now I want to write a function that has a different implementation depending on Face_index, Vertex_index or Edge_index but not depending on the typedef Mesh.
Here's how the user could use it:
std::cout << foo<void>() << std::endl;
std::cout << foo<Mesh::Face_index>() << std::endl;
std::cout << foo<Mesh::Vertex_index>() << std::endl;
std::cout << foo<Mesh::Edge_index>() << std::endl;
>> "Default foo() called"
>> "foo() for Face_index called"
>> "foo() for Vertex_index called"
>> "foo() for Edge_index called"
What I have tried
This first implementation work if foo had access to the Mesh tyedef, but this is not the case:
template <typename EI> //for Element Index
std::string foo(void)
{
return "Default foo() called";
}
template <>
std::string foo<Mesh::Face_index>(void)
{
return "foo() for Face_index called";
}
...
So I have tried something like that, but it doesn't work:
template <typename SM, typename EI> //for Surface Mesh and Element Index
std::string foo(void)
{
return "Default foo() called";
}
template <typename SM>
std::string foo<SM::Face_index>(void)
{
return "foo() for Face_index called";
}
...
Question
Do you know if it is possible to do what I want, and if so how to do it or do you have links to sites with explanations that could help me?
EDIT
Here is a simplified implementation of Surface_Mesh:
namespace CGAL
{
// Implementation for Surface_mesh::Vertex_index
class SM_Vertex_index
{
//...
};
// Implementation of Surfae_mesh::Face_index
class SM_Face_index
{
//...
};
template <typename P>
class Surface_mesh
{
public:
typedef SM_Vertex_index Vertex_index;
typedef SM_Face_index Face_index;
//... (P is used in the code)
};
}
In CGAL Face_index is - except for the case when the documentation is created - just a typedef for SM_Face_idex (typedef SM_Face_index Face_index;) and the same for all surface meshes.
So theoretically you could just do:
template <typename T>
std::string foo(void)
{
return "Default foo() called";
}
template <>
std::string foo<SM_Face_index>(void)
{
return "foo() for Face_index called";
}
This would work for the current CGAL versions, but I don't see anything in the documentation, that this will be guaranteed to be that way in the future.
The problem is that the documentation claims that Face_index is an actual class defined within Mesh and not that it is a typedef of a type independent of the surface mesh.
It is hard to get your mind, but I think the follow code may help you. It works in vs 2017.
// cls && cl x.cpp /EHsc && x
#include <iostream>
template<typename P, typename V, typename D> class ObjA
{
public:
typedef P POSI;
typedef V VERT;
D extra;
};
typedef ObjA<int, double, float> Mesh;
template<typename T> void foo() noexcept
{
std::cout << __FUNCSIG__ << "\n";
}
void foo() noexcept
{
std::cout << __FUNCSIG__ << "\n";
}
int main()
{
foo<Mesh::POSI>(); // void __cdecl foo<int>(void) noexcept
foo<Mesh::VERT>(); // void __cdecl foo<double>(void) noexcept
foo(); // void __cdecl foo(void) noexcept
return 0;
}
I have a templatized interface class, with a couple of implemented methods and a couple of virtual ones.
I need to specialize it in order to modify the signature of some methods, but others would remain the same.
Is there a way to bring the methods that remain the same back from the original template, either via using directive, by directly calling back to them or in another way, or I must copy/paste every single method back into the specialization?
template <typename T>
struct X {
void faa(T t) const { std::cout << t << '\n'; }
void foo() const { std::cout << "foo\n"; }
};
template <>
struct X<void> {
void faa() const { std::cout << "none\n"; }
// Something along these lines
// using X<T>::foo;
// void foo() const { X<T>::foo(); }
};
Seems so. You can't get the functions in X with different signatures using using directives. There is a better workaround than copying everything from the template to the specialization. You can use a "common base class".
template <typename T>
struct X_base {
void foo() const { std::cout << "foo\n"; }
};
template <typename T>
struct X : public X_base<T> {
void faa(T t) const { std::cout << t << '\n'; }
};
template <>
struct X<void> : public X_base<void> {
void faa() const { std::cout << "none\n"; }
};
In this way, X<void>::foo acts just like X_base<void>::foo, while X<T>::faa and X<void>::faa do not interfere with each other.
I have checked questions that are similar. This is close, but not a duplicate.
In essence I want to call a function on a parameter pack of base classes if present. I have a C++11 way of doing this that works, but it does not feel satisfactory to me.
Can someone offer a better [i.e. better performance and less boilerplate code]:
source code:
#include <iostream>
#include <type_traits>
using namespace std;
// a class initialised with an int that can't do it
struct A
{
A(int a) : _a(a) { }
void report() const { std::cout << _a << std::endl; }
private:
int _a;
};
// a class initialised with a string that can do it
struct B
{
B(std::string s) : _b (move(s)) { }
void report() const { std::cout << _b << std::endl; }
void do_it() { std::cout << "B did it with " << _b <<"!" << std::endl; }
private:
string _b;
};
// a class initialised with an int that can do it
struct D
{
D(int d) : _d(d) { }
void report() const { std::cout << _d << std::endl; }
void do_it() { std::cout << "D did it with " << _d <<"!" << std::endl; }
private:
int _d;
};
// a class initialised with a string that can't do it
struct E
{
E(std::string s) : _e(move(s)) { }
void report() const { std::cout << _e << std::endl; }
private:
string _e;
};
// a function enabled only if T::do_it is a member function pointer
// the bool is there just to make this function more attractive to the compiler
// than the next one, below
template<class T>
auto do_it(T& t, bool)
-> typename std::enable_if<std::is_member_function_pointer<decltype(&T::do_it)>::value, void>::type
{
t.do_it();
}
// a catch-all function called when do_it<T> is not valid
// the ... is less attractive to the compiler when do_it<T>(T&, bool) is available
template<class T>
void do_it(T& t, ...)
{
}
// a compound class derived from any number of classes - I am so lazy I work hard at
// being lazy.
template<class...Templates>
struct C : public Templates...
{
// construct from a parameter pack of arbitrary arguments
// constructing each base class with one argument from the pack
template<class...Args>
C(Args&&...args)
: Templates(std::forward<Args>(args))...
{
}
// private implementation of the dispatch mechanism here...
private:
// this will call ::do_it<T>(T&, bool) if T::do_it is a member function of T, otherwise
// calls ::do_it<T>(T&, ...)
template<class T>
void may_do_it()
{
::do_it(static_cast<T&>(*this), true);
}
// calls may_do_it for the last class in the parameter pack
template<typename T1>
void multi_may_do_it()
{
may_do_it<T1>();
}
// general case for calling do_it on a parameter pack of base classes
template<typename T1, typename T2, typename...Rest>
void multi_may_do_it()
{
may_do_it<T1>();
multi_may_do_it<T2, Rest...>();
}
// calls may_do_it for the last class in the parameter pack
template<typename T1>
void multi_report() const
{
static_cast<const T1&>(*this).report();
}
// general case for calling do_it on a parameter pack of base classes
template<typename T1, typename T2, typename...Rest>
void multi_report() const
{
static_cast<const T1&>(*this).report();
multi_report<T2, Rest...>();
}
// the functions we actually wish to expose here...
public:
// disptach T::do_it for each valid T in base class list
void do_it() {
multi_may_do_it<Templates...>();
}
// dispatch T::report, which must exist for each base class
void report() const {
cout << "-- all base classes reporting:" << endl;
multi_report<Templates...>();
cout << "-- all base classes reported" << endl;
}
};
int main()
{
C<A,B, D, E> c(10, "hello", 7, "goodbye");
c.report(); // all base classes must report
c.do_it(); // all base classes that can do_it, must.
return 0;
}
output:
Compiling the source code....
$g++ -std=c++11 main.cpp -o demo -lm -pthread -lgmpxx -lgmp -lreadline 2>&1
Executing the program....
$demo
-- all base classes reporting:
10
hello
7
goodbye
-- all base classes reported
B did it with hello!
D did it with 7!
I think this is about as boilerplate-free as you can make it.
// a function enabled only if T::do_it is a member function pointer
template<class T>
auto do_it(T* t)
-> typename std::enable_if<std::is_member_function_pointer<decltype(&T::do_it)>::value, void>::type
{
t->do_it();
}
// a catch-all function called when do_it<T> is not valid
// the const void * is less attractive to the compiler when do_it<T>(T*) is available
template<class T>
void do_it(const void *)
{
}
// a compound class derived from any number of classes - I am so lazy I work hard at
// being lazy.
template<class...Templates>
struct C : public Templates...
{
//constructor omitted
private:
using expander = int[];
public:
// disptach T::do_it for each valid T in base class list
void do_it() {
(void) expander{ 0, (::do_it<Templates>(this), 0)...};
}
// dispatch T::report, which must exist for each base class
void report() const {
cout << "-- all base classes reporting:" << endl;
(void) expander{ 0, (Templates::report(), 0)...};
cout << "-- all base classes reported" << endl;
}
};
Demo.
I'm trying to write a template function, but I have trouble specializing it for vector<> and another class at the same time. Here is the code I'm using :
// template definition
template< class T >
void f( const T& value)
{
cout << "DEFAULT" << endl;
}
// specialization for MyClass
template< class T >
void f<> ( const MyClass & value )
{
cout << "MyClass" << endl;
}
// specialization for vector
template< class T >
void f<>( const std::vector<T> & v )
{
cout << "vector" << endl;
}
MyClass and MyClass2 are defined as:
class MyClass{
virtual void a() = 0;
};
class MyClass2 : public MyClass{
void a(){}
};
Finally, the main function:
int main(int nArgs, char *vArgs[]){
MyClass2 e;
f<MyClass>(e);
}
Here is the error I get when I try compiling it using Visual Studio 2010:
c:\program files (x86)\microsoft visual studio 10.0\vc\include\vector(869): error C2259: 'MyClass' : cannot instantiate abstract class
This seems to be very specific to this particular situation: As soon as I remove the const modifiers, I change the vector into a list or I make MyClass concrete, everything works. But for my problem I need for this particular situation to work.
Is anybody having the same error as me, and more importantly does anybody know a fix/workaround for this?
I believe this:
// specialization for vector
template< class T >
void f<>( const std::vector<T> & v )
{
cout << "vector" << endl;
}
is not possible (even if your syntax were corrected, as Anton did in his answer), because it is not a full specialization of f (there are unbound type parameters). Partial function specialization is not allowed under the C++ standard.
There are a few other questions on Stack Overflow involving similar code with similar issues. This one (and the winning answer) seems to be quite relevant: Why function template cannot be partially specialized?
You can peruse the C++ standards for yourself, if you were feeling particularly masochistic. You might start from section 14.7.3 ("Explicit specialization") at page 368 of this document: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf (which is a semi-recent draft, but not the most up to date. It is free, however.)
As other answers have indicated:
your syntax for specialization is wrong
you cannot partially specialize a template function
...does anybody know a fix/workaround for this?
Since you are using the template argument in the argument list, you can use overloaded functions.
template <class T>
void f(const T& value)
{
std::cout << "DEFAULT" << std::endl;
}
void f(const MyClass& value)
{
std::cout << "MyClass" << std::endl;
}
template <class T>
void f(const std::vector<T>& v) // this is an overload, not a specialization
{
std::cout << "vector" << std::endl;
}
int main()
{
f(1);
MyClass2 e;
f(e);
f(std::vector<int>());
}
You have mistakes in specialization syntax.
Probably, it should look like this:
// MyClass
class MyClass{
virtual void a() = 0;
};
class MyClass2 : public MyClass{
void a(){}
};
// template definition
template< class T >
void f(const T& value)
{
cout << "DEFAULT" << endl;
};
// specialization for MyClass
template<>
void f(const MyClass & value)
{
cout << "MyClass" << endl;
};
// specialization for vector of MyClass
template<>
void f(const std::vector<MyClass> & v)
{
cout << "vector" << endl;
}
int main()
{
// Using template for any type
f(2);
// Using specialization for MyClass
MyClass2 e;
f<MyClass>(e);
// Using specialization for vector<MyClass>
vector<MyClass> vM;
f(vM);
}
Seached for this, but can't find a similar question. If there is one please close this question.
This isn't my real code, just an example to demonstrate :-
#include <iostream>
// Normal template class with a destructor
template <class T> class Test
{
public:
~Test() { std::cout << "Normal \n";}
};
// Partial specialization for arrays
template<class T> class Test<T[]>
{
public:
~Test() { std::cout << "Array \n"; }
};
int main()
{
Test<int[3]> i;
}
When I compile this it does not call the specialized version for arrays. If I replace the template with
template<class T> class Test<T[3]>
{
public:
~Test() { std::cout << "Array \n"; }
};
Then it does call the specialization but I want this to be called for any array not just ones of a specifed size. Is there any way to write a specialization that gets used for all arrays?
Capture the size with an additional non-type parameter:
#include <iostream>
template <class T> class Test
{
public:
~Test() { std::cout << "Normal \n";}
};
template<class T, size_t N> class Test<T[N]>
{
public:
~Test() { std::cout << "Array " << N << '\n'; }
};
int main()
{
Test<int[3]> i; // Array 3
Test<int[5]> j; // Array 5
}