Moving a generic template with restrictions out of the class definition - c++

The following example compiles and shows the correct endresult. EDIT: in the sense that three lines are printed.
#include <iostream>
using namespace std;
struct normal
{
static void log(const char * out) { cout << out << endl; }
};
struct other
{
static void log(const char * out) { cout << out << endl; }
};
//Implementation inside the class declaration
template<typename output = normal>
class LogUser_H
{
public:
void print() { output::log("template"); }
};
//Move Implementation moved out of the class declaration
template<typename output = normal>
class LogUser_CPP
{
public:
void print();
};
//Specialised definitions
void LogUser_CPP<struct normal>::print(void) { normal::log("normal specialisation"); }
void LogUser_CPP<struct other>::print(void) { other::log("other specialisation"); }
//Template definition ?
//void LogUser_CPP</*??*/output/*??*/>::print(void)
//{
// output::log("template");
//}
int main()
{
LogUser_H<> H;
H.print();
LogUser_CPP<> C1;
C1.print();
LogUser_CPP<other> C2;
C2.print();
}
The class LogUser_H has a method that calls a function in a struct. LogUser_CPP is meant to do the same with the twist that I want to move the method definition out of the class definition and write it below. Doing so I no longer have a definition for output and I can not get to the function in structs that fulfil the output requirement. I can however provide specialized versions of struct and compile that way.
How can I delete the two specialized implementations void LogUser_CPP<struct normal>::print(void) and void LogUser_CPP<struct other>::print(void)? In want to replace them with a generic implementation looking something like the commented out implementation void LogUser_CPP</*??*/output/*??*/>::print(void).
EDIT 1:
I tried the following:
//Specialised definitions
//void LogUser_CPP<struct normal>::print(void) { normal::log("normal specialisation"); }
//void LogUser_CPP<struct other>::print(void) { other::log("other specialisation"); }
template<>
void LogUser_CPP<>::print(void)
{
output::log("template");
}
This will not compile.
EDIT 2:
I tried the following:
//Specialised definitions
//void LogUser_CPP<struct normal>::print(void) { normal::log("normal specialisation"); }
//void LogUser_CPP<struct other>::print(void) { other::log("other specialisation"); }
template<typename output>
void LogUser_CPP<>::print(void)
{
output::log("template");
}
This will not compile.
The error is error C3211: 'LogUser_CPP<normal>::print' : explicit specialization is using partial specialization syntax, use template <> instead
Could this be compiler specific? This computer has VS2013 Express on it.

Use:
template <>
void LogUser_CPP<normal>::print(void) { normal::log("normal specialisation"); }
template <>
void LogUser_CPP<other>::print(void) { other::log("other specialisation"); }
or
template<typename output>
void LogUser_CPP<output>::print(void)
{
output::log("template");
}

Related

C++ syntactic sugar or technique for prototype generation when using template specialization

I wonder what is the preferred C++ way for the generation of method prototypes,
when using template specialization? The technique I'm after
should scale well with the number of the foo class methods, see below.
The marked block of the reproducer has to be replaced.
Please no code snippets managed by hand or by a script.
Some additional small modifications (perhaps in the header) might be possible.
For brevity the templated class A is placed beside the typedef for Aint.
CRTP solutions are disfavored. Usage of C++17 (not later) is allowed.
Has to compile with VS2019 recent g++ and clang++.
Edit 2020-02-09:
Removing the marked block all together,
this compiles fine with
Compiler Explorer's x64 MSVC 19.14 compiler.
So do we have a compiler issue here for g++ and clang++?
// begin of testspec.h
template<class T>
class A
{
public:
A();
void foo1();
void foo2();
void foo3();
};
typedef A<int> Aint;
// end of testspec.h
// begin of testspec.cpp
#include "testspec.h"
#include <iostream>
/////////////// can this block be simplified? //////////
template<>
void
A<int>::foo1();
template<>
void
A<int>::foo2();
template<>
void
A<int>::foo3();
/////////////// can this block be simplified? //////////
template<>
A<int>::A()
{
foo1();
foo2();
foo3();
std::cout << "hello world" << std::endl;
}
template<>
void
A<int>::foo1()
{
std::cout << "foo1" << std::endl;
}
template<>
void
A<int>::foo2()
{
std::cout << "foo2" << std::endl;
}
template<>
void
A<int>::foo3()
{
std::cout << "foo3" << std::endl;
}
// end of testspec.cpp
// begin of main.cpp
#include "testspec.h"
int main()
{
Aint a;
return 0;
};
// end of main.cpp
Assuming that there is a part of A that does not get specialized, then the portion of A that you are trying to allow for modifiable behavior via specialization can be accomplished by adopting a policy pattern.
class APolicy {
template <class, class> friend class A;
void foo1 ();
void foo2 ();
void foo3 ();
};
template <class T, class P = APolicy>
class A {
void foo1() { P().foo1(); }
void foo2() { P().foo1(); }
void foo3() { P().foo1(); }
};
And then instead of specializing A<int>, you implement a policy IntPolicy, and then instantiate A<int, IntPolicy>.

How to choose among similar functions from different namespaces based on template parameter

the title and the code is self-explanatory,
Is such a thing possible?how?
Is it encouraged? if not, what is the alternative?
thanks
#include <iostream>
using namespace std;
namespace A
{
void foo()
{
cout << "In A\n";
}
}
namespace B
{
void foo()
{
cout << "In B\n";
}
}
template <typename X>
struct Foo {
void foo()
{
X::foo();
}
};
int main()
{
Foo<A> _foo;
_foo.foo();
return 0;
}
You cannot use a namespace as a template type (namespaces are not types); your code does not compile. The best you can hope for is to use Argument Dependent Lookup (ADL), but it won't work for functions taking no parameters.
If you rename your member function, you can find it via ADL by using a proxy tag:
namespace A
{
struct tag {};
void foo(tag)
{
std::cout << "In A\n";
}
}
namespace B
{
struct tag {};
void foo(tag)
{
std::cout << "In B\n";
}
}
template<class Tag>
struct Foo {
void fooADL()
{
foo(Tag{});
}
};
int main()
{
Foo<A::tag> f;
f.fooADL();
}
Is such a thing possible?
No, you can't parametrise a namespace.
if not, what is the alternative?
Use classes, rather than namespaces, to provide parametrisable scopes for the functions:
struct A {
static void foo();
};
struct B {
static void foo();
}

how to adjust a c++ code to work with template class

Following codes are part of a Red Black Tree program which has to take item as a char or int, so I decided to use a template class, however I don't know how to extend it through the complete program and the compiler sends me thousand errors:
The code has German names, so if it makes it easier to understand, I will translate some of them:
baum = tree
knote = node
links = left
rechts = right
rot = red
doppel = double
mittlere = middle
eltern = parent
einfuegen = insert
rs = rb = red black
Knote.hpp
#pragma once
template <class T>
class Knote {
public:
Knote(T data = 0);
bool rot;
T item;
Knote *links;
Knote *rechts;
Knote *eltern;
};
Knote.cpp
#include "Knote.hpp"
Knote<int>::Knote(int data)
{
this->item = data;
eltern = nullptr;
links = nullptr;
rechts = nullptr;
rot = true;
}
now how should I do it for the rest?
Baum.hpp
#pragma once
#include "Knote.hpp"
#include <vector>
class Baum
{
public:
Baum();
void einfuegen(int x);
void ausgabe_levelorder();
void ausgabe_inorder();
private:
Knote<int>* head;
void rs_einfuegen(Knote<int>* &knote, Knote<int>* &eltern, int x, bool sw);
int rot(Knote<int>* &knote);
void links_rotation(Knote<int> * &links_knote);
void rechts_rotation(Knote<int> * &links_knote);
void levelorder(Knote<int>* knote, std::vector<Knote<int>*> &knoteQueue, int niveau, std::vector<int> &niveauQueue);
void sort_levelorder(std::vector<Knote<int>*> &knoteQueue, std::vector<int> &niveauQueue);
void inorder(Knote<int>* knote);
};
Baum.cpp
#include "Baum.hpp"
#include <iostream>
using namespace std;
Baum::Baum()
{
...
}
// XXX
void Baum::einfuegen(int x)
{
...
}
// XXX
int Baum::rot(Knote<int>* &knote)
{
...
}
// XXX
void Baum::rs_einfuegen(Knote<int> *& knote, Knote<int> *&eltern, int x, bool sw)
{
...
}
// XXX
void Baum::links_rotation(Knote<int>* &links_knote)
{
...
}
// XXX
void Baum::rechts_rotation(Knote<int>* &rechts_knote)
{
...
}
// XXX
void Baum::ausgabe_levelorder()
{
...
}
// XXX
void Baum::levelorder(Knote<int>* knote, vector<Knote<int>*> &knoteQueue, int niveau, vector<int> &niveauQueue)
{
...
}
// XXX
void Baum::sort_levelorder(vector<Knote<int>*> &knoteQueue, vector<int> &niveauQueue)
{
...
}
// XXX
void Baum::ausgabe_inorder()
{
inorder(head->rechts);
cout << endl;
}
// XXX
void Baum::inorder(Knote<int>* knote)
{
if (knote != nullptr)
{
inorder(knote->links);
cout << knote->item << " ";
inorder(knote->rechts);
}
}
Don't need to use Knote<T> in the class. Just use Knote. Instead of
Knote<T> *links;
Knote<T> *rechts;
Knote<T> *eltern;
just use:
Knote *links;
Knote *rechts;
Knote *eltern;
When you use the class template, make sure you provide a template parameter.
Knote* head;
is not right. You need to use
Knote<int>* head;
or
Knote<char>* head;
You pick the type that is appropriate for Baum.
Move the implementation of Knote to the .h file from the .cpp file. See Why can templates only be implemented in the header file?.
For Knote.h, your template <typename T> line should be template <class T>
Also, in your constructor for Knote, you can't assign an int (data) to a T variable (item). For the constructor, you should have T data, instead of int data, since you don't know what type data needs to be (because it's a template).
Templated classes also don't have a cpp file. The implementation has to go in the .h after the class declaration (unless forward declared). If you do want to separate your header and "implementation" code parts, keep the .h as normal, but make an .hpp file for your method implementations. In the .h after the class declaration, put #include "Knote.hpp".
For normal methods, the format goes like the following:
template <typename T>
void Knote<T>::myMethod(parameters)
{
//normal method stuff
}
For friend methods that take the templated class as a parameter, such as an overloaded the insertion operator (<<), the format goes like this:
//in class declaration in .h
template <class T>
class Bob
{
//variables here
template <typename U>
void myfunc(Bob<U> value); //have to use a different template variable
}
//define as normal in the .hpp (or further down the file if no .hpp used)

C++ class depends on function, but function depends on class

I can't compile this code because the function declaration depends on the class declaration, and the class declaration depends on the function declaration. Please help.
#include <iostream>
using namespace std;
void simulate(Policy& p);
class Policy {
public:
Policy(int);
int x;
void eval();
};
int main() {
Policy p(23);
return 0;
}
Policy::Policy(int y) { x = y; }
void Policy::eval() { simulate(this); }
void simulate(Policy& p) { cout << ++p.x << endl; }
Place the prototype of your function below the definition of your class, but above the member functions.

How to call generic template function in a specialization version

Have a problem about how to call the generic template version in a specialization version.
Here is the sample code. But the "vector::push_back(a)" calls itself recursively.
#include <iostream>
#include <vector>
using namespace std;
namespace std
{
template<>
void vector<int>::push_back(const int &a)
{
cout << "in push_back: " << a << endl;
vector::push_back(a); // Want to call generic version
}
}
int main()
{
vector<int> v;
v.push_back(10);
v.push_back(1);
return 0;
}
When you create specialization for some template (no difference class of function), you tell to compiler to generate that one instead of general. So in fact if you have specialization you have no general version for that specialization and you can't call it, because it doesn't exists.
You can simply extract the code into another template function:
template<typename T>
void baseF(T t) { ... }
template<typename T>
void F(T t) { baseF<T>(t); }
template<>
void F<int>(int t) { baseF<int>(t); }
Well, to complement, I think it works for template function specification in some situations.
#include <iostream>
#include <vector>
using namespace std;
class Base
{
public:
virtual int test() {return 0;}
};
class Derived : public Base
{
public:
virtual int test() {return 1;}
};
template<class T>
void TestOutput(T* a)
{
cout << a->test() << endl;
}
template<>
void TestOutput(Derived* a)
{
cout << "something else" << endl;
TestOutput<Base>(a);
}
int main()
{
Derived d;
TestOutput(&d);
}
I compiled it with visual studio 2013 and the output is:
something else
1
Although I don't think you can always find a TestOutput function of Base to call the generic one.