So i have something like that:
template<unsigned int W,unsigned int H>
class Class
{
int data[W][H];
Class(const (&_data)[W][H])
{
for (int x=0;x<W;x++)
for (int y=0;y<H;y++)
data[x][y] = _data[x][y];
}
template<class... args>
Class()
{
/// black magic
}
}
What could i replace the "black magic", so the second constructor will accept W*H ints?
Example:
Class<3,2> class1(1,2,3,4,5,6);
There are alternative answers which might be more practical and simpler to implement, but I'll show how you could actually do this with a compile-time for-loop for purposes of demonstrating black-magic.
Here is a compile-time for-loop.
/* Compile-time for-loop up to N. */
template <std::size_t N>
struct For {
/* Call f<I>(args...) N times. */
template <typename F, typename... Args>
void operator()(F &&f, Args &&... args) const {
Impl<0, N>()(std::forward<F>(f), std::forward<Args>(args)...);
}
private:
/* Forward declaration. */
template <std::size_t I, std::size_t End>
struct Impl;
/* Base case. Do nothing. */
template <std::size_t End>
struct Impl<End, End> {
template <typename F, typename... Args>
void operator()(F &&, Args &&...) const { /* Do nothing. */ }
}; // Impl<End, End>
/* Recursive case. Call f<I>(args...), then recurse into next step. */
template <std::size_t I, std::size_t End>
struct Impl {
template <typename F, typename... Args>
void operator()(F &&f, Args &&... args) const {
std::forward<F>(f).template operator()<I>(std::forward<Args>(args)...);
Impl<I + 1, End>()(std::forward<F>(f), std::forward<Args>(args)...);
}
}; // Impl<I, End>
}; // For<N>
Here is a simple use case of it.
struct Print {
template <std::size_t I>
void operator()(int x, int y) const {
std::cout << "Iteration " << I << ": " << x << ' ' << y << std::endl;
}
}; // Print
For<3>()(Print(), 1, 2);
Outputs
Iteration 0: 1 2
Iteration 1: 1 2
Iteration 2: 1 2
Now with this we can nest this compile-time for-loop just like how we could nest a run-time for-loop. Here is the Matrix class using this For<> template.
/* Defines an M by N Matrix, (Row by Col). */
template <std::size_t M, std::size_t N>
class Matrix {
public:
/* Our underlying M by N matrix. */
using Data = std::array<std::array<int, N>, M>;
/* Construct off of M * N arguments. */
template <typename... Args>
Matrix(Args &&... args) {
static_assert(sizeof...(Args) == M * N,
"The number of arguments provided must be M * N.");
ForEach(AssignImpl(),
data_,
std::forward_as_tuple(std::forward<Args>(args)...));
}
/* Print each element out to std::cout. */
void Write(std::ostream &strm) const {
ForEach(WriteImpl(), strm, data_);
}
private:
/* Our outer for loop. Call InnerFor() M times.
Resembles: 'for (std::size_t i = 0 ; i < M; ++i) {' */
template <typename F, typename... Args>
void ForEach(F &&f, Args &&... args) const {
For<M>()(InnerFor(), std::forward<F>(f), std::forward<Args>(args)...);
}
/* Our inner for loop. Call ForBody() N times.
Resembles: 'for (std::size_t j = 0; j < N; ++j) {' */
struct InnerFor {
template <std::size_t I, typename F, typename... Args>
void operator()(F &&f, Args &&... args) const {
For<N>()(ForBody<I>(),
std::forward<F>(f),
std::forward<Args>(args)...);
}
}; // InnerFor
/* The body of our for loop. Call f<I, J>(args...); */
template <std::size_t I>
struct ForBody {
template <std::size_t J, typename F, typename... Args>
void operator()(F &&f, Args &&... args) const {
std::forward<F>(f)
.template operator()<I, J>(std::forward<Args>(args)...);
}
}; // ForBody<I>
/* Given the M by N array and a tuple of length M * N, assign the array. */
struct AssignImpl {
template <std::size_t I, std::size_t J, typename Arg>
void operator()(Data &data, Arg &&arg) const {
data[I][J] = std::get<I * N + J>(std::forward<Arg>(arg));
}
}; // AssignImpl
/* Given an output stream and our data, print the data at (I, J). */
struct WriteImpl {
template <std::size_t I, std::size_t J>
void operator()(std::ostream &strm, const Data &data) const {
strm << data[I][J] << std::endl;
}
}; // WriteImpl
/* Our underlying M by N array. */
Data data_;
}; // Matrix
Here is a quick demonstration of construction and writing to std::cout.
int main() {
Matrix<3, 2> matrix{101, 102,
201, 202,
301, 302};
matrix.Write(std::cout);
}
First of all, there's some syntax errors in your example as missing semicolon after class declaration and the constructors being private.
Apart from that, if you want to store the numbers in row-major order, then you should declare your matrix/2d-array as int data[H][W] (height first, then width).
To store the values from a variadic pack you can simply expand them inside the ctor of a container, e.g. std::array, and make use of list-initialization.
template <typename... Args>
Class(Args&&... args) {
const std::array<int, H * W> temp{std::forward<Args>(args)...};
/* ... */
};
I've also used universal references and perfect forwarding to preserve the reference type of the pack.
To populate your 2d-array you simply have to iterate over all elements in temp and store them in the member array.
for (std::size_t h = 0; h != H; ++h)
for (std::size_t w = 0; w != W; ++w)
data[h][w] = temp[h * W + w];
See a full example here
This works:
#include <array>
#include <utility>
#include <iostream>
template<unsigned W,unsigned H>
struct Foo
{
std::array<std::array<int, H>, W> data;
template<typename... Args>
Foo(Args&&... args):
data{ std::forward<Args>(args)... }
{}
};
int main()
{
Foo<2,2> x(1,2,3,4);
for( auto&& a : x.data ) {
for( unsigned z : a ) {
std::cout << z << ",";
}
std::cout << "\n";
}
but exposes the order of storage in your inner array.
std::array is a syntactic sugar wrapped around raw C arrays.
you could use std::initializer_list as a constructor parameter, since your array only is of type int[][].
Class(std::initializer_list<int> il)
{
if(il.size() < W*H)
throw string("Insufficient elements");//if lesser no. of elements are given.
auto it = il.begin();// iterator to the first element of the list.
for(int i =0;i< W;++i)
{
for(int j =0; j < H;++j)
{
data[i][j] = *it++;// increment the iterator
}
}
}
call site will look like this:
Class<3,2> c{1,2,3,4,5,6};
or
Class<3,2> c = {1,2,3,4,5,6};
if more elements are given then extras are discarded. initializer_list can give type safety, and will give you a diagnostic if narrowing is found.
Related
I have a method that takes an index-able object as a template parameter, something like:
template <typename OBJ>
int foo(int n, OBJ o)
{
int x = 0;
for (int i = 0; i < n; ++i) {
x += o[i];
}
return x;
}
Is there a way I can pass a lambda function in for the o parameter? In other words, having the lambda be call-able via the [] operator rather than the () operator?
template<class F>
struct square_bracket_invoke_t {
F f;
template<class T>
auto operator[](T&& t)const
-> typename std::result_of< F const&(T&&) >::type
{ return f(std::forward<T>(t)); }
};
template<class F>
square_bracket_invoke_t< typename std::decay<F>::type >
make_square_bracket_invoke( F&& f ) {
return {std::forward<F>(f)};
}
Live example.
Code is C++11 and has basically zero overhead.
int main() {
std::cout << foo( 6, make_square_bracket_invoke([](int x){ return x; } ) ) << "\n";
}
result is 0+1+2+3+4+5 aka 15.
Is this a good idea? Maybe. But why stop there?
For max amusement:
const auto idx_is = make_square_bracket_invoke([](auto&&f){return make_square_bracket_invoke(decltype(f)(f));});
int main() {
std::cout << foo( 6, idx_is[[](int x){ return x; }] ) << "\n";
}
You can do that by:
Creating a class template, a functor, that has the operator[] defined.
Implementing the operator[] in terms of the operator() of a std::function.
Storing the lambda in a wrapped std::function as a member variable of the class template.
Here's a demonstrative program.
#include <iostream>
#include <functional>
template <typename OBJ>
int foo(int n, OBJ o)
{
int x = 0;
for (int i = 0; i < n; ++i) {
x += o[i];
}
return x;
}
template <typename> struct Functor;
template <typename R> struct Functor<R(int)>
{
using ftype = std::function<R(int)>;
Functor(ftype f) : f_(f) {}
R operator[](int i) const { return f_(i); }
ftype f_;
};
int main()
{
Functor<int(int)> f = {[](int i) -> int {return i*i;}};
std::cout << foo(10, f) << std::endl;
}
and its output
285
Live demo
PS
Functor is not the appropriate name here. It does not overload the function call operator. I suspect there is a more appropriate name.
Well, if it helps, here's a way to forward a wrapper class's operator[] to your lambda's operator().
template<class F>
struct SubscriptWrapper_t {
F f_;
template<class T> auto operator[](T const& t_) const -> decltype(f_(t_)) {
return f_(t_);
}
};
template<class F>
SubscriptWrapper_t<typename std::decay<F>::type> SubscriptWrapper(F&& f_) {
return{std::forward<F>(f_)};
}
I use wrappers like this a lot. They're convenient, and they don't seem to have any computational overhead, at least when compiled by GCC. You can make one for at or even make one for find.
EDIT: Updated for C++11 (and updated to be able to return a reference)
A sketch of a wrapper type that would do this.
template<typename UnaryFunction>
class index_wrapper
{
public:
index_wrapper(UnaryFunction func) : func(std::move(func)) {}
template<typename T>
std::invoke_result_t<UnaryFunction, T> operator[](T&& t)
{ return func(std::forward<T>(t)); }
private:
UnaryFunction func;
};
With usage
#include <iostream>
template <typename OBJ>
int foo(int n, OBJ o)
{
int x = 0;
for (int i = 0; i < n; ++i) {
x += o[i];
}
return x;
}
int main()
{
index_wrapper f([](int i) -> int { return i*i; });
std::cout << foo(10, f) << std::endl;
}
You might want to restrict it to a single parameter type, so that you can provide member type aliases similar to std::vector::reference et.al.
I am following this code snippet which makes it easier to pass a member function to an interface expecting a C-style callback (that is, the interface expects a function pointer to the callback, and a void* pointer to user data which will in turn be passed to the callback). Effectively I want to convert Helper::M to Helper::V below.
I am trying to modify the snippet to automatically deduce the template parameters. Here is my current attempt.
#include <iostream>
template <typename R, typename T, typename... Args>
struct Helper {
using V = R (*)(void*, Args...);
using M = R (T::*)(Args...);
template <M m>
static R Fn(void* data, Args... args) {
return (static_cast<T*>(data)->*m)(std::forward<Args...>(args...));
}
};
template <typename R, typename T, typename... Args>
typename Helper<R, T, Args...>::V Cast(R (T::*m)(Args...)) {
return Helper<R, T, Args...>::template Fn<m>;
}
int CIntf(void* data, int (*f)(void*, int)) { return f(data, 1); }
struct UserData {
int x;
int Add(int y) { return x + y; }
};
int main(int argv, char** argc) {
UserData data = {4};
// Explicit parameters; works.
std::cout << CIntf(&data, Helper<int, UserData, int>::Fn<&UserData::Add>)
<< "\n";
// Deduced parameters; fails.
std::cout << CIntf(&data, Cast(&UserData::Add)) << "\n";
return 0;
}
I tried to compile with gcc -std=c++11 -lstdc++. The explicit parameters method works fine, but the deduced parameters method gives the following error:
tmp.cc: In instantiation of ‘typename Helper<R, T, Args>::V Cast(R (T::*)(Args ...)) [with R = int; T = UserData; Args = {int}; typename Helper<R, T, Args>::V = int (*)(void*, int)]’:
tmp.cc:30:58: required from here
tmp.cc:15:42: error: no matches converting function ‘Fn’ to type ‘using V = int (*)(void*, int) {aka int (*)(void*, int)}’
return Helper<R, T, Args...>::template Fn<m>;
^~~~~
tmp.cc:8:12: note: candidate is: template<int (UserData::* m)(int)> static R Helper<R, T, Args>::Fn(void*, Args ...) [with R (T::* m)(Args ...) = m; R = int; T = UserData; Args = {int}]
static R Fn(void* data, Args... args) {
Note that it correctly deduced the template parameters, but failed to convert Helper<int, UserData, int>::Fn<m> to int (*)(void*, int); why? This same conversion succeeded in the explicit case (unless m is somehow different from &UserData::Add).
Unfortunately you'll have to use a macro for this:
#define makeFunc(method) &Helper<decltype(method)>::Fn<method>
And redefine your helper like this for it to work:
template <typename T>
struct Helper;
template <typename R, typename T, typename... Args>
struct Helper<R(T::*)(Args...)>
The reason why you can't use deduction for this, is that deduction only works on function arguments which are run-time values. And you need to use a method's address as template argument which should be a compile-time value.
So when you do this:
return Helper<R, T, Args...>::template Fn<m>;
you are passing a run-time value m as a template argument which is impossible.
For reference, here is the complete code using the macro. Also note the use of std::forward in the original code was incorrect for multiple arguments (see this answer).
#include <iostream>
#include <utility>
template <typename T>
struct Helper;
template <typename R, typename T, typename... Args>
struct Helper<R (T::*)(Args...)> {
template <R (T::*m)(Args...)>
static R Fn(void* t, Args... args) {
return (static_cast<T*>(t)->*m)(std::forward<Args>(args)...);
}
};
#define VOID_CAST(m) &Helper<decltype(m)>::Fn<m>
struct UserData {
int x;
int Add1(int y) { return x + y; }
int Add2(int y, int z) { return x + y + z; }
};
int Call1(void* data, int (*f)(void*, int)) { return (*f)(data, 1); }
int Call2(void* data, int (*f)(void*, int, int)) { return (*f)(data, 1, 2); }
int main() {
UserData data = {4};
std::cout << Call1(&data, VOID_CAST(&UserData::Add1)) << "\n";
std::cout << Call2(&data, VOID_CAST(&UserData::Add2)) << "\n";
return 0;
}
I have a tensor classes of rank N which wrap data stored in an array. For example, a rank-3 tensor would have dimensions (d0,d1,d2) and a unique element would be accessed with the multi-index (i0,i1,i2) from the underlying array of length d0*d1*d2. If d0=d1=d2=10, i0=1, i1=2, i2=3, then element 123 of the array would be accessed.
I've implemented a recursively defined class which computes single array index from the multi-index as follows:
template<size_t N>
class TensorIndex : TensorIndex<N-1> {
private:
size_t d;
public:
template<typename...Ds>
TensorIndex( size_t d0, Ds...ds ) : TensorIndex<N-1>( ds... ), d(d0) {}
template<typename...Is>
size_t index( size_t i0, Is...is ) {
return i0+d*TensorIndex<N-1>::index(is...);
}
};
template<>
struct TensorIndex<1> {
TensorIndex( size_t ) {}
size_t index( size_t i ) { return i; }
};
Which reverses the desired order.
TensorIndex<3> g(10,10,10);
std::cout << g.index(1,2,3) << std::endl;
outputs 321. What would be a simple way to reverse the order of the arguments for the constructor and index functions?
Edit:
I tried implementing using the suggested approach of reversing the variadic arguments, but this was suboptimal as it required reversing the arguments for both index and the constructor and the necessary helper functions for these two cases would appear slightly different. The initializer list answer looks more straightforward.
No need of recursion nor to reverse, you can use initializer-list to call an evaluation function that accumulates index from left to right. The function object called in the initalizer-list should have a non-void return type :
#include <cstddef>
#include <iostream>
using namespace std;
template<size_t N>
class TensorIndex {
public:
template<typename... Args>
TensorIndex(Args... args) : dims{static_cast<size_t>(args)...}
{
static_assert(sizeof...(Args) == N,
"incorrect number of arguments for TensorIndex constructor");
}
template<typename... Args>
size_t index(Args... args) {
static_assert(sizeof...(Args) == N,
"incorrect number of arguments for TensorIndex::index()");
IndexEval eval{dims};
Pass pass{eval(args)...}; // evaluate from left to right : initializer-list
return eval.get_res();
}
private:
const size_t dims[N];
class IndexEval {
size_t k = 0;
size_t res = 0;
const size_t* dims;
public:
IndexEval(const size_t* dims) : dims{dims} {}
size_t operator()(size_t i) {
return res = res * dims[k++] + i;
}
size_t get_res() const { return res; }
};
struct Pass {
template<typename... Args> Pass(Args...) {}
};
};
int main()
{
TensorIndex<3> g(10, 10, 10);
cout << g.index(1, 2, 3) << endl;
}
I want to pass two functions with different signature into a same slot of class template parameter (one each time).
Ignore the strict syntax, this is what I want :-
void hf1 (int a) { std::cout<< "hf1" <<std::endl; }
void hf2 (int a, int i){ std::cout<< "hf2 "<<i<<std::endl; }
template<hfX> class Collection{
int i_=56;
public: test(){
if( "hfX has 1 param" ){hfX(0);} //call hf1
else {hfX(0,i_);} //call hf2
}
};
int main(){
Collection<&hf1> test1; test1.test(); // print "hf1"
Collection<&hf2> test2; test2.test(); // print "hf2 56"
}
Here is the code that works OK, but its usage is not so convenient :-
template<typename ... AA> using hfX = void(*)(AA ... );
void hf1 (int a) { std::cout<< "hf1" <<std::endl; }
void hf2 (int a, int i) { std::cout<< "hf2 "<<i <<std::endl; }
template <typename Tf, Tf F>
class Collection;
template <typename ... I, hfX<I...> F>
class Collection<hfX<I...>, F>{
public:
int i_=56;
template <std::size_t N = sizeof...(I)>
typename std::enable_if<N == 1U, void>::type test (){
F(0);
}
template <std::size_t N = sizeof...(I)>
typename std::enable_if<N == 2U, void>::type test (){
F(0,i_);
}
};
The usage:-
int main () {
Collection<hfX<int>, hf1> test1; //<--- #A dirty signature
Collection<hfX<int,int>, hf2> test2; //<--- #B dirty signature
test1.test(); // print "hf1"
test2.test(); // print "hf2 56"
}
Live version : https://ideone.com/f20BEk
Question
It would be nice if I can call it without explicit redundant signature.
Collection<hf1> test1; //or &hf
Collection<hf2> test2;
How to improve code (especially around hfX and Collection) to make its usage easier?
I don't know how to make what do you want with functions.
But if you can, instead of functions, accept to use static method in classes or structs (and pass that classes/structs as template argument)...
#include <iostream>
struct sf1
{ static void hf (int a) { std::cout << "hf1" << std::endl; } };
struct sf2
{ static void hf (int a, int i) { std::cout << "hf2 " << i << std::endl; } };
template <typename S>
class Collection
{
private:
int i_ = 56;
public:
template <typename T = S>
decltype(T::hf(0)) test() { S::hf(0); /*call sf1::hf */ }
template <typename T = S>
decltype(T::hf(0, 0)) test() { S::hf(0,i_); /*call sf2::hf */ }
};
int main ()
{
Collection<sf1> test1; test1.test(); // print "hf1"
Collection<sf2> test2; test2.test(); // print "hf2 56"
}
I want to define n-dimensional data structure using std::vector. I have a problem with definition of operator(). Lets have a look at a sample 2D structure
class my_data {
public:
my_data (size_t N, size_t M) : tab(N*M), _N(N), _M(M) {}
const double& operator() (size_t i, size_t j) const {
return tab.at(i * M + j);
}
double& operator() (size_t i, size_t j) {
return tab.at(i * M + j);
}
private:
std::vector<double> tab;
size_t _N;
size_t _M;
};
I would like to define such a structures for any dimension using templates , but I don't know if it is possible. So basically what I would like to have is something like that
my_data<4> vec (1,2,3,4);
defines 4D 'tensor' with sizes 1,2,3,4 (number of all elements 1*2*3*4). You can now access and change values by typing
vec (0,0,0,0) = 2.0;
The below solution uses some of the C++14 and C++1z features, but they can be easily ported to C++11:
#include <vector>
#include <utility>
#include <array>
#include <cstddef>
namespace detail
{
template <typename T, typename S>
class my_data;
template <typename T, std::size_t... Is>
class my_data<T, std::index_sequence<Is...>>
{
public:
my_data(decltype(Is)... size)
: t((size * ...)), s{{ size... }}
{}
T& operator()(decltype(Is)... i)
{
return t.at(index({{ i... }}));
}
const T& operator()(decltype(Is)... i) const
{
return t.at(index({{ i... }}));
}
private:
std::size_t index(const std::array<std::size_t, sizeof...(Is)>& a) const
{
std::size_t ind = a[0];
for (std::size_t i = 1; i < a.size(); ++i)
{
ind = ind * s[i] + a[i];
}
return ind;
}
std::vector<T> t;
const std::array<std::size_t, sizeof...(Is)> s;
};
}
template <typename T, std::size_t N>
using my_data = detail::my_data<T, std::make_index_sequence<N>>;
Test:
int main()
{
my_data<double, 4> vec(1,2,3,4);
vec(0,0,0,0) = 2.0;
}
DEMO
DEMO (C++11)