Easiest way to deduce templates - c++

As an example, I have the following function template:
template <typename X, typename Y, typename Z>
void f(X &x, Y &y, Z &z) { ... }
I need to write a user interface in the form of
void fxyz(std::string optionX, std::string optionY, std::string optionZ)
Here, optionX, optionY, optionZ can be "x1" or "x2", "y1" or "y2", "z1" or "z2" respectively. Every option corresponds to a different type, i.e., X1, X2, Y1, ... .Currently I implemented it like this:
template <typename Y, typename Z>
void fx(std::string &optionX, Y &y, Z &z)
{
if (optionX == "x1") {
X1 x; f <X1, Y, Z> (x, y, z); }
else {
X2 x; f <X2, Y, Z> (x, y, z); }
}
template <typename Z>
void fxy(std::string &optionX, std::string &optionY, Z &z)
{
if (optionY == "y1") {
Y1 y; fx <Y1, Z> (optionX, y, z); }
else {
Y2 y; fx <Y2, Z> (optionX, y, z); }
}
void fxyz(std::string &optionX, std::string &optionY, std::string &optionZ)
{
if (optionZ == "z1") {
Z1 z; fxy <Z1> (optionX, optionY, z); }
else {
Z2 z; fxy <Z2> (optionX, optionY, z); }
}
This seems a lot of work especially if there are more template parameters. Any easier way to achieve what I want?
Thanks!

Map into variants, then visit them.
std::variant<X1, X2> choose_X(std::string_view choice) {
if(choice == "x1") return X1();
else if(choice == "x2") return X2();
}
std::variant<Y1, Y2> choose_Y(std::string_view choice) {
if(choice == "y1") return Y1();
else if(choice == "y2") return Y2();
}
std::variant<Z1, Z2> choose_Z(std::string_view choice) {
if(choice == "z1") return Z1();
else if(choice == "z2") return Z2();
}
You are not getting out of writing some set of rules to get from strings to objects, of course. A possible variation is
std::map<std::string, std::function<std::variant<X1, X2>()>> choices_X{
{"x1", []() { return X1(); }},
{"x2", []() { return X2(); }}
};
Then simply
std::string choice_X, choice_Y, choice_Z;
std::visit(
[](auto&&... xs) -> decltype(auto) { return f(std::forward<decltype(xs)>(xs)...); },
choose_X(choice_X), choose_Y(choice_Y), choose_Z(choice_Z)
);
O(n^2) code length is now O(n) code length (in number of parameters).

Related

How to check type being assigned to result of call operator?

I'm trying to make a simple matrix class
Relevant parts of "mymat.h"
#ifndef _MYMAT_H_GUARD_
#define _MYMAT_H_GUARD_
#include <iostream>
constexpr auto MYMAT_ERR_UNEXPECTED_TYPE = "Error, unexpected type!";
constexpr auto MYMAT_ERR_CODE_UNEXPECTED_TYPE = 0;
constexpr auto MYMAT_ERR_OUT_OF_BOUND = "Error, out of bound!";
constexpr auto MYMAT_ERR_CODE_OUT_OF_BOUND = 0;
template <typename T>
class MYMAT{
public:
T* data;
int x, y;
public:
MYMAT(int x, int y);
~MYMAT();
template <typename C>
void set(int x, int y, C val);
template<typename C>
bool checkType(C val) const;
void print_mat();
public:
T& operator ()(int x, int y);
private:
bool inRange(int x, int y);
};
#endif // !_MYMAT_H_GUARD_
template<typename T>
inline MYMAT<T>::MYMAT(int x, int y){
this->data = new T[x * y]();
this->x = x;
this->y = y;
}
template<typename T>
inline MYMAT<T>::~MYMAT(){
delete this->data;
}
template<typename T>
inline void MYMAT<T>::print_mat(){
int x, y;
for (y = 0; y < this->y; y++)
{
for (x = 0; x < this->x; x++)
{
std::cout << this->data[y * this->x + x] << ' ';
}
std::cout << std::endl;
}
std::cout << std::endl;
}
template<typename T>
inline bool MYMAT<T>::inRange(int x, int y){
return !((x < 1) && (x > this->x) && (y < 1) && (y > this->y));
}
template<typename T>
template<typename C>
inline void MYMAT<T>::set(int x, int y, C val){
if (this->checkType(val)) {
if (this->inRange(x, y)) {
this->data[(y - 1) * this->x + (x - 1)] = val;
}
else {
std::cout << MYMAT_ERR_OUT_OF_BOUND;
exit(MYMAT_ERR_CODE_OUT_OF_BOUND);
}
}
else {
std::cout << MYMAT_ERR_UNEXPECTED_TYPE;
exit(MYMAT_ERR_CODE_UNEXPECTED_TYPE);
}
}
template<typename T>
inline T& MYMAT<T>::operator()(int x, int y)
{
return this->data[this->x * (y - 1) + (x - 1)];
}
template<typename T>
template<typename C>
inline bool MYMAT<T>::checkType(C val) const
{
return std::is_same_v<T, C>;
}
And below is how I call matrix and use set method
#include <iostream>
#include "mymat.h"
int main()
{
MYMAT<int> m(3, 3);
m.set(2, 2, 500);
m.print_mat();
m.set(2, 2, 500.0);
m.print_mat();
}
It prints
0 0 0
0 500 0
0 0 0
Error, unexpected type!
But when call operator is used:
#include <iostream>
#include "mymat.h"
int main()
{
MYMAT<int> m(3, 3);
m(2, 2) = 500;
m.print_mat();
m(2, 2) = 500.0;
m.print_mat();
}
It prints:
0 0 0
0 500 0
0 0 0
0 0 0
0 500 0
0 0 0
As you see, the value is casted from double to int.
How can I apply the condition in set() for call operator?
To achieve what you want:
m(2, 2) = 500.0; // do custom checks for conversions from
// right hand side to left hand side
returning a T& from operator() is not going to work, because you have no control over implicit conversions to T. In this case, you can't prevent the conversion from double to int.
Instead, you can return a type from operator() that you write yourself, so you have all the control you need over implicit conversions. This type needs to hold onto the information on the left hand side, which is the this pointer of m, and the arguments to operator(). It only needs to support operator= to check for implicit conversions from the right hand side:
private:
struct Wrapper
{
MYMAT *t; // holds onto the this pointer
int x, y;
template <typename C>
void operator=(C val)
{
t->set(x, y, val); // uses MYMAT::set to do the conversion checking
}
};
Now you can declare your operator() like this:
public:
Wrapper operator ()(int x, int y);
and define it like this:
template<typename T>
inline auto MYMAT<T>::operator()(int x, int y) -> Wrapper
{
return {this, x, y};
}
Here's a demo.

Recusion and Templates in C++

I try to compute derivatives using Tangent mode. I tried to implement it using recursion.
I got the following problem: I got a recursion with Templates which compiles forever.
template <typename T>
void dern(int n, const T &x, T &dy)
{
using DCO_T = typename dco::gt1s<T>::type;
DCO_T _x, _y;
dco::value(_x) = x;
dco::derivative(_x) = 1;
if (n > 1)
{
dern(--n, _x, _y);
}
else
{
f(_x, _y);
}
dy = dco::derivative(_y);
}
if I try to write them out it works perfectly fine:
template <typename T>
void der1(const T &x, T &dy)
{
using DCO_T = typename dco::gt1s<T>::type;
DCO_T _x, _y;
dco::value(_x) = x;
dco::derivative(_x) = 1;
f(_x, _y);
dy = dco::derivative(_y);
}
template <typename T>
void der2(const T &x, T &dy)
{
using DCO_T = typename dco::gt1s<T>::type;
DCO_T _x, _y;
dco::value(_x) = x;
dco::derivative(_x) = 1;
der1(_x, _y);
dy = dco::derivative(_y);
}
template <typename T>
void der3(const T &x, T &dy)
{
using DCO_T = typename dco::gt1s<T>::type;
DCO_T _x, _y;
dco::value(_x) = x;
dco::derivative(_x) = 1;
der2(_x, _y);
dy = dco::derivative(_y);
}
template <typename T>
void der4(const T &x, T &dy)
{
using DCO_T = typename dco::gt1s<T>::type;
DCO_T _x, _y;
dco::value(_x) = x;
dco::derivative(_x) = 1;
der3(_x, _y);
dy = dco::derivative(_y);
}
My supervisor thinks it doesn't work because of the template. Does anyone know a fix?
n should be a compile time parameter passed as template argument.
template <int n, typename T>
void dern(const T &x, T &dy)
{
using DCO_T = typename dco::gt1s<T>::type;
DCO_T _x, _y;
dco::value(_x) = x;
dco::derivative(_x) = 1;
if constexpr (n > 1) {
dern<n - 1>(_x, _y);
} else {
f(_x, _y);
}
dy = dco::derivative(_y);
}
A compile time recursion can't depend on a runtime variable.
Call it with, e.g.
dern<4>(x, y);

How to represent a 3D array with map?

How can I represent a 3D array like
myarray[1000][1000][1000];
this is a large array which gives memory limit exceeded. Every cell will not be used so there is a huge waste of memory. I want to map 3 numbers and the value, Is there any other way to do this?
#include <map>
#include <iostream>
struct MapIndex{
int x, y, z;
MapIndex()
:x(0), y(0), z(0){
}
MapIndex(int x_, int y_, int z_)
:x(x_), y(y_), z(z_){
}
};
bool operator<(const MapIndex &v1, const MapIndex &v2){
if (v1.z > v2.z)
return false;
if (v1.z < v2.z)
return true;
if (v1.y > v2.y)
return false;
if (v1.y < v2.y)
return true;
if (v1.x < v2.x)
return true;
return false;
}
template<typename Val> struct Array3D{
typedef std::map<MapIndex, Val> Data;
Data data;
Val defaultValue;
const Val& getValue(int x, int y, int z) const{
MapIndex index(x, y, z);
Data::const_iterator found = data.find(index);
if (found == data.end())
return defaultValue;
return found->second;
}
void setValue(int x, int y, int z, const Val &val){
data.insert(std::make_pair(MapIndex(x, y, z), val));
}
bool hasValue(int x, int y, int z) const{
Data::const_iterator found = data.find(MapIndex(x, y, z));
return found != data.end();
}
Array3D(const Val& defaultValue_ = Val())
:defaultValue(defaultValue_){
}
};
int main(int argc, char** argv){
Array3D<int> ints;
std::cout << ints.hasValue(0, 1, 2) << std::endl;
std::cout << ints.getValue(0, 1, 2) << std::endl;
ints.setValue(0, 1, 2, 47);
std::cout << ints.hasValue(0, 1, 2) << std::endl;
std::cout << ints.getValue(0, 1, 2) << std::endl;
return 0;
}

How to map a bool to a 3d point struct with std::map?

How do I use the following struct:
struct point
{
int x;
int y;
int z;
};
as a key for std::map<point, bool>? How should I define operator< for two points?
Standard library containers like std::map require that your ordering is a "Strict Weak Ordering", so you have to be very careful when designing one.
The typical approach for a 3-ary tuple looks like this:
bool operator<(const point& other) const
{
if (x != other.x)
return (x < other.x);
if (y != other.y)
return (y < other.y);
return (z < other.z);
}
It's like a comparator for just x, but with the difference that if the two xs are the same, you fall through to compare ys. If they are the same, then similarly you fall through to the z comparison.
Of course, boost::tuple<int,int,int> would make this utterly unnecessary.
Update Adding the all-inclusive have-your-cake-and-eat-it-too no-drawback solution here. IMHO it rocks!
#include <boost/tuple/tuple_comparison.hpp>
struct point
{
int x, y, z;
point(int x, int y, int z) : x(x), y(y), z(z) {}
bool operator<(const point& rhs) const
{
return boost::tie(x, y, z) < boost::tie(rhs.x, rhs.y, rhs.z);
}
};
Here is the kicker: it all optimizes away. Compile:
int main()
{
point a(1,2,3), b(3,2,1);
bool lt = a<b;
return lt?0:255;
}
With g++ -O2 yields the following in assembly.
main:
.LFB1132:
pushl %ebp
xorl %eax, %eax
movl %esp, %ebp
popl %ebp
ret
.LFE1132:
The compiler was able to optimize the whole of this program to ... return 0 effectively. That is pretty neat.
Here goes the simple answer:
struct point
{
point(int x, int y, int z)
: x(x), y(y), z(z) {}
int x;
int y;
int z;
bool operator<(const point& rhs) const
{
if (x<rhs.x) return true;
if (x==rhs.x)
{
if (y<rhs.y) return true;
if (y==rhs.y) return z<rhs.z;
}
return false;
}
};
Also, I would consider looking for a redefinition of my struct that will allow using std::lexicographical_compare
#include <algorithm>
// ...
bool operator<(const point& rhs) const
{
return std::lexicographical_compare(&xyz, &xyz+3, &rhs.xyz, &rhs.xyz+3);
}
One lazy way to do it:
bool operator<( point const &pt ) const
{
return ::boost::make_tuple(x,y,z) <
::boost::make_tuple(pt.x,pt.y,pt.z);
}
The simplest way to write this is like this:
bool operator<(const point& p) const
{
if(x < p.x)
{
return true;
}
else if(p.x < x)
{
return false;
}
if( y < p.y)
{
return true;
}
else if( p.y < y)
{
return false;
}
if( z < p.z)
{
return true;
}
else if(p.z < z)
{
return false;
}
return false;
}
if they're supposed to be ordered in a certain way, you'll want to specify that exact way (for example by euclidean distance from 0/0/0). If all you want is to distinguish different points, you could do something like
x == x2 ? (y == y2 ? (z < z2) : y < y2) : x < x2
Just a guess guys,
bool operator<(const point& other) const
{
return( memcmp( (void*) this, (void*) &other, sizeof(point)) < 0);
}
Of course, the order is kind of weird since x,y and z are signed values, but this should be suitable to order into a std::map, isn't it ?

C/C++ macro/template blackmagic to generate unique name

Macros are fine.
Templates are fine.
Pretty much whatever it works is fine.
The example is OpenGL; but the technique is C++ specific and relies on no knowledge of OpenGL.
Precise problem:
I want an expression E; where I do not have to specify a unique name; such that a constructor is called where E is defined, and a destructor is called where the block E is in ends.
For example, consider:
class GlTranslate {
GLTranslate(float x, float y, float z); {
glPushMatrix();
glTranslatef(x, y, z);
}
~GlTranslate() { glPopMatrix(); }
};
Manual solution:
{
GlTranslate foo(1.0, 0.0, 0.0); // I had to give it a name
.....
} // auto popmatrix
Now, I have this not only for glTranslate, but lots of other PushAttrib/PopAttrib calls too. I would prefer not to have to come up with a unique name for each var. Is there some trick involving macros templates ... or something else that will automatically create a variable who's constructor is called at point of definition; and destructor called at end of block?
Thanks!
I would not do this personally but just come up with unique names. But if you want to do it, one way is to use a combination of if and for:
#define FOR_BLOCK(DECL) if(bool _c_ = false) ; else for(DECL;!_c_;_c_=true)
You can use it like
FOR_BLOCK(GlTranslate t(1.0, 0.0, 0.0)) {
FOR_BLOCK(GlTranslate t(1.0, 1.0, 0.0)) {
...
}
}
Each of those names are in separate scopes and won't conflict. The inner names hide the outer names. The expressions in the if and for loops are constant and should be easily optimized by the compiler.
If you really want to pass an expression, you can use the ScopedGuard trick (see Most Important const), but it will need some more work to write it. But the nice side is, that we can get rid of the for loop, and let our object evaluate to false:
struct sbase {
operator bool() const { return false; }
};
template<typename T>
struct scont : sbase {
scont(T const& t):t(t), dismiss() {
t.enter();
}
scont(scont const&o):t(o.t), dismiss() {
o.dismiss = true;
}
~scont() { if(!dismiss) t.leave(); }
T t;
mutable bool dismiss;
};
template<typename T>
scont<T> make_scont(T const&t) { return scont<T>(t); }
#define FOR_BLOCK(E) if(sbase const& _b_ = make_scont(E)) ; else
You then provide the proper enter and leave functions:
struct GlTranslate {
GLTranslate(float x, float y, float z)
:x(x),y(y),z(z) { }
void enter() const {
glPushMatrix();
glTranslatef(x, y, z);
}
void leave() const {
glPopMatrix();
}
float x, y, z;
};
Now you can write it entirely without a name on the user side:
FOR_BLOCK(GlTranslate(1.0, 0.0, 0.0)) {
FOR_BLOCK(GlTranslate(1.0, 1.0, 0.0)) {
...
}
}
If you want to pass multiple expressions at once, it's a bit more tricky, but you can write an expression template that acts on operator, to collect all expressions into a scont.
template<typename Derived>
struct scoped_obj {
void enter() const { }
void leave() const { }
Derived const& get_obj() const {
return static_cast<Derived const&>(*this);
}
};
template<typename L, typename R> struct collect
: scoped_obj< collect<L, R> > {
L l;
R r;
collect(L const& l, R const& r)
:l(l), r(r) { }
void enter() const { l.enter(); r.enter(); }
void leave() const { r.leave(); l.leave(); }
};
template<typename D1, typename D2>
collect<D1, D2> operator,(scoped_obj<D1> const& l, scoped_obj<D2> const& r) {
return collect<D1, D2>(l.get_obj(), r.get_obj());
}
#define FOR_BLOCK(E) if(sbase const& _b_ = make_scont((E))) ; else
You need to inherit the RAII object from scoped_obj<Class> like the following shows
struct GLTranslate : scoped_obj<GLTranslate> {
GLTranslate(float x, float y, float z)
:x(x),y(y),z(z) { }
void enter() const {
std::cout << "entering ("
<< x << " " << y << " " << z << ")"
<< std::endl;
}
void leave() const {
std::cout << "leaving ("
<< x << " " << y << " " << z << ")"
<< std::endl;
}
float x, y, z;
};
int main() {
// if more than one element is passed, wrap them in parentheses
FOR_BLOCK((GLTranslate(10, 20, 30), GLTranslate(40, 50, 60))) {
std::cout << "in block..." << std::endl;
}
}
All of these involve no virtual functions, and the functions involved are transparent to the compiler. In fact, with the above GLTranslate changed to add a single integer to a global variable and when leaving subtracting it again, and the below defined GLTranslateE, i did a test:
// we will change this and see how the compiler reacts.
int j = 0;
// only add, don't subtract again
struct GLTranslateE : scoped_obj< GLTranslateE > {
GLTranslateE(int x):x(x) { }
void enter() const {
j += x;
}
int x;
};
int main() {
FOR_BLOCK((GLTranslate(10), GLTranslateE(5))) {
/* empty */
}
return j;
}
In fact, GCC at optimization level -O2 outputs this:
main:
sub $29, $29, 8
ldw $2, $0, j
add $2, $2, 5
stw $2, $0, j
.L1:
add $29, $29, 8
jr $31
I wouldn't have expected that, it optimized quite well!
If your compiler supports __COUNTER__ (it probably does), you could try:
// boiler-plate
#define CONCATENATE_DETAIL(x, y) x##y
#define CONCATENATE(x, y) CONCATENATE_DETAIL(x, y)
#define MAKE_UNIQUE(x) CONCATENATE(x, __COUNTER__)
// per-transform type
#define GL_TRANSLATE_DETAIL(n, x, y, z) GlTranslate n(x, y, z)
#define GL_TRANSLATE(x, y, z) GL_TRANSLATE_DETAIL(MAKE_UNIQUE(_trans_), x, y, z)
For
{
GL_TRANSLATE(1.0, 0.0, 0.0);
// becomes something like:
GlTranslate _trans_1(1.0, 0.0, 0.0);
} // auto popmatrix
I think it's now possible to do something like this:
struct GlTranslate
{
operator()(double x,double y,double z, std::function<void()> f)
{
glPushMatrix(); glTranslatef(x, y, z);
f();
glPopMatrix();
}
};
then in the code
GlTranslate(x, y, z,[&]()
{
// your code goes here
});
Obviously, C++11 is needed
The canonical way as described in one answer is to use a lambda expression as the block, in C++ you can easily write a template function
with<T>(T instance, const std::function<void(T)> &f) {
f(instance);
}
and use it like
with(GLTranslate(...), [] (auto translate) {
....
});
but the most common reason for wanting a mechanism for avoiding defining names in your scope are long functions / methods that do lots of things. You might try a modern OOP / clean code inspired style with very short methods / functions for a change if this kind of problem keeps bothering you 🤔
Using C++17, a very simple macro leading to an intuitive usage:
#define given(...) if (__VA_ARGS__; true)
And can be nested:
given (GlTranslate foo(1.0, 0.0, 0.0))
{
foo.stuff();
given (GlTranslate foo(1.0, 2.0, 3.0))
{
foo.stuff();
...
}
}