custom type casting - pybind11 - casting

I'm trying to cast a custom type according to the pybind11 docs. But I don't know how to cast a struct with multiple field. what I'm trying to do so far is below
struct vect {
vect(int x, int y): x(x), y(y){}
int x, y;
};
int main() {
py::scoped_interpreter guard{};
py::module my_mod = py::module::import("my_mod");
vect v(1,2);
py::object result = my_mod.attr("do_something")(v);
vect v2 = result.cast<vect>();
return 0;
}
someone help me to cast it
namespace pybind11 {
namespace detail {
template <> struct type_caster<vect> {
// how to cast c++ --> python and pyton --> c++
};
}
} // namespace pybind11::detail

Related

how to get a class to take in another classes parameters?

I want to have my grid class constructor to take in drivers_location parameters , but it keeps giving me these errors.
https://imgur.com/a/y4MZqso
#include <iostream>
#include <string>
using namespace std;
class drivers_location {
public:
drivers_location() = default;
drivers_location(string name, float xx, float yy){
x = xx;
y = yy;
name = driver_name;
}
private:
float x{};
float y{};
string driver_name;
};
class grid {
public:
grid() = default;
grid(drivers_location(string name, float xx, float yy));
private:
};
int main() {
drivers_location p;
float pointx{ 2.0 };
float pointy{ 3.0 };
grid m[5];
m[0] = { {"abdul" , pointx, pointy }};
}
I want the grid to take in parameters of drivers_location without using inheritance if that's possible
The correct syntax for declaring a constructor takes argument of type driver_location is as shown below. Note that you don't have to specify the 2 parameters of driver_location when defining the constructor for grid that has a parameter of type driver_location.
class grid {
public:
grid() = default;
//---vvvvvvvvvvvvvvvv---->this is how we specify that this ctor has a parameter of type drivers_location
grid(drivers_location){
//add your code here
}
private:
};
I would also recommend using a good c++ book.

Converting between instances of a class template using a member function

I have a couple of strong types that are just aliases of a class template that contains useful shared code.
template <typename T>
struct DiscretePosition {
public:
int x{0};
int y{0};
// ... useful generic functions
};
struct ChunkTag{};
struct TileTag{};
using ChunkPosition = DiscretePosition<ChunkTag>;
using TilePosition = DiscretePosition<TileTag>;
I would like to write a constructor or helper function to help me convert one of these types to the other.
TilePosition tilePosition{1, 1};
ChunkPosition chunkPosition{tilePosition};
// or
ChunkPosition chunkPosition{tilePosition.asChunkPosition()};
This constructor would just take the underlying x, y and scale them to match the other type using a constant.
Is there a way to do this, or would I need to use a free function?
Here is one possible generic solution that allows you to specialize a get_scaling_factor function for conversions you want to allow:
godbolt link
#include <iostream>
struct ChunkTag{};
struct TileTag{};
template<typename T, typename U>
consteval double get_scaling_factor();
template<>
consteval double get_scaling_factor<ChunkTag, TileTag>() {
return 2;
}
template <typename T>
struct DiscretePosition {
public:
int x{0};
int y{0};
// ... useful generic functions
DiscretePosition(int x, int y) : x(x), y(y) {}
template<typename U>
explicit DiscretePosition(const DiscretePosition<U>& other)
: x(other.x * get_scaling_factor<T, U>())
, y(other.y * get_scaling_factor<T, U>())
{}
};
using ChunkPosition = DiscretePosition<ChunkTag>;
using TilePosition = DiscretePosition<TileTag>;
int main() {
TilePosition tilePosition{1, 1};
ChunkPosition chunkPosition{tilePosition};
std::cout << chunkPosition.x << ", " << chunkPosition.y << std::endl;
// or
// ChunkPosition chunkPosition{tilePosition.asChunkPosition()};
}
The accepted answer worked fine, but I ended up doing something different as a more general-purpose solution.
For each strong type that I wanted to add functionality to, I turned it into a full derived class:
class ChunkPosition : public DiscretePosition<DiscreteImpl::ChunkTag>
{
public:
ChunkPosition();
ChunkPosition(int inX, int inY);
explicit ChunkPosition(const TilePosition& tilePosition);
};
class TilePosition : public DiscretePosition<DiscreteImpl::TileTag>
{
public:
TilePosition();
TilePosition(int inX, int inY);
explicit TilePosition(const ChunkPosition& chunkPosition);
};

Walk over variants that share the same member and get it?

In the example below, is it possible to create a function getX that walks over the variant cases and get the x variable?
#include <variant>
class A {
int x = 0;
};
class B {
int x = 1;
};
class C {
int x = 1;
};
std::variant<A, B, C> variant;
One obvious solution would be:
int getX(std::variant<A, B, C>& variant) {
if (std::holds_alternative<A>(variant)) {
} else //...
}
but then every time I add a new variant it'd be tedious to write code that treats the new case.
Is there a more automated, perhaps constexpr way of doing this? I think it's even possible to do for different variable names in each class. The one call that works should be the chosen one for the class.
That's a "visit". You can do this:
#include <variant>
struct A {
int x = 0;
};
struct B {
int x = 1;
};
struct C {
int x = 1;
};
std::variant<A, B, C> var = A{};
int main() {
int n = std::visit([](auto & obj) {return obj.x;}, var);
}
Note, passing visit a generic lambda (taking an auto parameter) is actually a template, so whatever type is in the variant, that's the type of reference obj will be. I had to change your classes to structs so that the data was accessible.

VexCL vector of structs?

So I know that it is possible to use custom types with OpenCL. But I haven't been able to use them with VexCL. Creating a device vector of structs works fine, but I can't perform any operations.
As I haven't found any examples using custom types with VexCL my question is is that even possible? Thanks in advance.
VexCL does not support operations with vectors of structs out of the box. You will need to help it a bit. First, you need to tell VexCL how to spell the type name of the struct. Let's say you have the following struct defined on the host side:
struct point2d {
double x;
double y;
};
You need to provide a specification of the vex::type_name_impl struct that will generate a string corresponding to the type name of the struct. Remember that the code you are generating is C99:
namespace vex {
template <> struct type_name_impl<point2d> {
static std::string get() { return "struct point2d"; }
};
}
You will also need to make sure every generated kernel knows about your struct. This may be achieved with vex::push_program_header() function after the VexCL context has been initialized:
vex::push_program_header(ctx, "struct point2d { double x; double y; };");
This will allow you to declare vectors of the struct, and to pass the vectors to custom functions. That should be general enough. Here is the complete example:
#include <vexcl/vexcl.hpp>
// Host-side definition of the struct.
struct point2d {
double x, y;
};
// We need this for code generation.
namespace vex {
template <>
struct type_name_impl<point2d> {
static std::string get() { return "struct point2d"; }
};
}
int main() {
const size_t n = 16;
vex::Context ctx(vex::Filter::Env);
std::cout << ctx << std::endl;
// After this, every kernel will have the struct declaration in header:
vex::push_program_header(ctx, "struct point2d { double x; double y; };");
// Now we may define vectors of the struct:
vex::vector<point2d> x(ctx, n);
vex::vector<double> y(ctx, n);
// We won't be able to use the vectors in any expressions except for
// custom functions, but that should be enough:
VEX_FUNCTION(point2d, init, (double, x)(double, y),
struct point2d p = {x, y}; return p;
);
VEX_FUNCTION(double, dist, (point2d, p),
return sqrt(p.x * p.x + p.y * p.y);
);
x = init(3,4);
y = dist(x);
std::cout << y << std::endl;
}
And here is the kernel that will be generated for the assignment operation of y = dist(x);:
struct point2d { double x; double y; };
double dist
(
struct point2d p
)
{
return sqrt(p.x * p.x + p.y * p.y);
}
kernel void vexcl_vector_kernel
(
ulong n,
global double * prm_1,
global struct point2d * prm_2
)
{
for(ulong idx = get_global_id(0); idx < n; idx += get_global_size(0))
{
prm_1[idx] = dist( prm_2[idx] );
}
}

How to call function pointer in STL

I am curious about how to call function pointer in a map structure. Here is the details:
#include<iostream>
#include<map>
#include<vector>
#include<string.h>
using namespace std;
class FuncP;
typedef int(FuncP::*func) (int, int);
class FuncP
{
public:
map<int, func> fmap;
map<int, string> fstring;
public:
FuncP(){}
void initial();
int max(int x, int y);
int min(int x, int y);
int call(int op, int x, int y)
{
return (this->*fmap[op])(x, y);
}
};
void FuncP::initial()
{
fmap[0] = &FuncP::max;
fmap[1] = &FuncP::min;
fstring[0] = "fdsfaf";
}
int FuncP::min(int x, int y)
{
return (x<y)?x:y;
}
int FuncP::max(int x, int y)
{
return (x<y)?y:x;
}
int main()
{
func h = &FuncP::max;
FuncP *handle = new FuncP();
handle->initial();
cout<< handle->call(0, 1, 4); //1
cout<< (handle->FuncP::*fmap)[0](1,5); //2
return 0;
}
For the number 2 (handle->FuncP::*fmap)0; The compiler gives a error:
‘fmap’ was not declared in this scope
I am not sure why it happened. What the difference of the number 1 and 2 call methods?
As commented by Piotr, a correct way would be
(handle->*(handle->fmap[0]))(1, 5);
Explanation:
handle->fmap[0] gives you the function pointer. To call it, you need to dereference it, giving *(handle->fmap[0]) (parentheses optional)
and call it on the respecting object (handle), leaving us with the expression above.
This is essentially the same as your above statement (this->*fmap[op])(x, y) except of handle->fmap[0]instead offmap[op].