How to call multiple templated functions with a single call? - c++11

I'm working on a program (an emulator) where I need to access the memory map of the emulated machine. It's done using a templated function (read).
This function returns data size depending on the templated parameter (ie read< uint8_t >(0x10) will return 8 bits of data from memory address 0x10, read< uint32_t >(0x20) will return 32 bits of data from memory address 0x20), etc.
This is done using 3 arrays of pointers to functions (read_8_handler_, read_16_handler_, read_32_handler_), linking each address to a particular function.
Initialization of these arrays is done calling initializeHandlers 3 times for each linked function :
// default handlers
initializeHandler<uint8_t>(0x00, 0xFF, readDummy<uint8_t>);
initializeHandler<uint16_t>(0x00, 0xFF, readDummy<uint16_t>);
initializeHandler<uint32_t>(0x00, 0xFF, readDummy<uint32_t>);
// rom handlers
initializeHandler<uint8_t>(0x60, 0x6F, readRom<uint8_t>);
initializeHandler<uint16_t>(0x60, 0x6F, readRom<uint16_t>);
initializeHandler<uint32_t>(0x60, 0x6F, readRom<uint32_t>);
This leads to a lot of redundancy, as each handler has to use 3 lines for initialization.
So my question is : can I use a one liner to initialize one handler, without providing the template arguments, like this :
initializeHandler(0x00, 0xFF, readDummy);
initializeHandler(0x60, 0x6F, readRom);
?
I think it can be done using template template parameters, but I'm not fluent enough in templates to find out how to do it ...
Here's the complete example, which can be tested here
#include <iostream>
#include <cstdlib>
#include <array>
#include <tuple>
template <typename R, typename ...ARGS> using function = R(*)(ARGS...);
template<typename T> using ReadType = function<T, const uint32_t>;
template<class ReadType> using ReadHandlerType = std::array<ReadType, 0x100>;
template<typename T> using ReadHandler = ReadHandlerType<ReadType<T>>;
ReadHandler<uint8_t> read_8_handler_;
ReadHandler<uint16_t> read_16_handler_;
ReadHandler<uint32_t> read_32_handler_;
template<typename T>
T readDummy( const uint32_t addr) {
return sizeof(T{});
}
template<typename T>
T readRom( const uint32_t addr) {
return sizeof(T{})*2;
}
template<typename T>
void initializeHandler(uint32_t begin,
uint32_t end,
ReadType<T> func) {
auto t = std::tie(read_8_handler_, read_16_handler_, read_32_handler_);
for (uint32_t current = begin; current <= end; ++current) {
auto& handler = std::get < ReadHandler<T>& >(t);
handler[current & 0xFF] = func;
}
}
template<typename T>
T read(const uint32_t addr) {
auto& handler = std::get < ReadHandler<T>& >(std::tie(read_8_handler_, read_16_handler_, read_32_handler_));
return handler[addr](addr);
}
int main()
{
initializeHandler<uint8_t>(0x00, 0xFF, readDummy<uint8_t>);
initializeHandler<uint16_t>(0x00, 0xFF, readDummy<uint16_t>);
initializeHandler<uint32_t>(0x00, 0xFF, readDummy<uint32_t>);
initializeHandler<uint8_t>(0x60, 0x6F, readRom<uint8_t>);
initializeHandler<uint16_t>(0x60, 0x6F, readRom<uint16_t>);
initializeHandler<uint32_t>(0x60, 0x6F, readRom<uint32_t>);
std::cout << read<uint16_t>( 0x20) << std::endl;
std::cout << read<uint16_t>( 0x60) << std::endl;
}

You can turn readDummy and readRom into types convertible to ReadType<T> and the use fold expressions like this:
template<typename T>
struct readDummy
{
operator ReadType<T>() const {
return [] (const uint32_t addr) -> T {
return sizeof(T{});
};
}
};
template<typename T>
struct readRom
{
operator ReadType<T>() const {
return [] (const uint32_t addr) -> T {
return sizeof(T{})*2;
};
}
};
template <template <class> class ReadType, class... T>
auto initialize(uint32_t begin, uint32_t end)
{
(initializeHandler<T>(begin, end, ReadType<T>{}), ...);
}
initialize<readDummy, uint8_t, uint16_t, uint32_t>(0x00, 0x0FF);
initialize<readRom, uint8_t, uint16_t, uint32_t>(0x60, 0xFF);

Related

Composing boost::variant visitors for recursive variants

I have an application with several boost::variants which share many of the fields. I would like to be able to compose these visitors into visitors for "larger" variants without copying and pasting a bunch of code. It seems straightforward to do this for non-recursive variants, but once you have a recursive one, the self-references within the visitor (of course) point to the wrong class. To make this concrete (and cribbing from the boost::variant docs):
#include "boost/variant.hpp"
#include <iostream>
struct add;
struct sub;
template <typename OpTag> struct binop;
typedef boost::variant<
int
, boost::recursive_wrapper< binop<add> >
, boost::recursive_wrapper< binop<sub> >
> expression;
template <typename OpTag>
struct binop
{
expression left;
expression right;
binop( const expression & lhs, const expression & rhs )
: left(lhs), right(rhs)
{
}
};
// Add multiplication
struct mult;
typedef boost::variant<
int
, boost::recursive_wrapper< binop<add> >
, boost::recursive_wrapper< binop<sub> >
, boost::recursive_wrapper< binop<mult> >
> mult_expression;
class calculator : public boost::static_visitor<int>
{
public:
int operator()(int value) const
{
return value;
}
int operator()(const binop<add> & binary) const
{
return boost::apply_visitor( *this, binary.left )
+ boost::apply_visitor( *this, binary.right );
}
int operator()(const binop<sub> & binary) const
{
return boost::apply_visitor( *this, binary.left )
- boost::apply_visitor( *this, binary.right );
}
};
class mult_calculator : public boost::static_visitor<int>
{
public:
int operator()(int value) const
{
return value;
}
int operator()(const binop<add> & binary) const
{
return boost::apply_visitor( *this, binary.left )
+ boost::apply_visitor( *this, binary.right );
}
int operator()(const binop<sub> & binary) const
{
return boost::apply_visitor( *this, binary.left )
- boost::apply_visitor( *this, binary.right );
}
int operator()(const binop<mult> & binary) const
{
return boost::apply_visitor( *this, binary.left )
* boost::apply_visitor( *this, binary.right );
}
};
// I'd like something like this to compile
// class better_mult_calculator : public calculator
// {
// public:
// int operator()(const binop<mult> & binary) const
// {
// return boost::apply_visitor( *this, binary.left )
// * boost::apply_visitor( *this, binary.right );
// }
// };
int main(int argc, char **argv)
{
// result = ((7-3)+8) = 12
expression result(binop<add>(binop<sub>(7,3), 8));
assert( boost::apply_visitor(calculator(),result) == 12 );
std::cout << "Success add" << std::endl;
// result2 = ((7-3)+8)*2 = 12
mult_expression result2(binop<mult>(binop<add>(binop<sub>(7,3), 8),2));
assert( boost::apply_visitor(mult_calculator(),result2) == 24 );
std::cout << "Success mult" << std::endl;
}
I would really like something like that commented out better_mult_expression to compile (and work) but it doesn't -- because the this pointers within the base calculator visitor don't reference mult_expression, but expression.
Does anyone have suggestions for overcoming this or am I just barking down the wrong tree?
Firstly, I'd suggest the variant to include all possible node types, not distinguishing between mult and expression. This distinction makes no sense at the AST level, only at a parser stage (if you implement operator precedence in recursive/PEG fashion).
Other than that, here's a few observations:
if you encapsulate the apply_visitor dispatch into your evaluation functor you can reduce the code duplication by a big factor
your real question seems not to be about composing variants, but composing visitors, more specifically, by inheritance.
You can use using to pull inherited overloads into scope for overload resolution, so this might be the most direct answer:
Live On Coliru
struct better_mult_calculator : calculator {
using calculator::operator();
auto operator()(const binop<mult>& binary) const
{
return boost::apply_visitor(*this, binary.left) *
boost::apply_visitor(*this, binary.right);
}
};
IMPROVING!
Starting from that listing let's shave off some noise!
remove unncessary AST distinction (-40 lines, down to 55 lines of code)
generalize the operations; the <functional> header comes standard with these:
namespace AST {
template <typename> struct binop;
using add = binop<std::plus<>>;
using sub = binop<std::minus<>>;
using mult = binop<std::multiplies<>>;
using expr = boost::variant<int,
recursive_wrapper<add>,
recursive_wrapper<sub>,
recursive_wrapper<mult>>;
template <typename> struct binop { expr left, right; };
} // namespace AST
Now the entire calculator can be:
struct calculator : boost::static_visitor<int> {
int operator()(int value) const { return value; }
template <typename Op>
int operator()(AST::binop<Op> const& binary) const {
return Op{}(boost::apply_visitor(*this, binary.left),
boost::apply_visitor(*this, binary.right));
}
};
Here your variant can add arbitrary operations without even needing to touch the calculator.
Live Demo, 43 Lines Of Code
Like I mentioned starting off, encapsulate visitation!
struct Calculator {
template <typename... T> int operator()(boost::variant<T...> const& v) const {
return boost::apply_visitor(*this, v);
}
template <typename T>
int operator()(T const& lit) const { return lit; }
template <typename Op>
int operator()(AST::binop<Op> const& bin) const {
return Op{}(operator()(bin.left), operator()(bin.right));
}
};
Now you can just call your calculator, like intended:
Calculator calc;
auto result1 = calc(e1);
It will work when you extend the variant with operatios or even other literal types (like e.g. double). It will even work, regardless of whether you pass it an incompatible variant type that holds a subset of the node types.
To finish that off for maintainability/readability, I'd suggest making operator() only a dispatch function:
Full Demo
Live On Coliru
#include <boost/variant.hpp>
#include <iostream>
namespace AST {
using boost::recursive_wrapper;
template <typename> struct binop;
using add = binop<std::plus<>>;
using sub = binop<std::minus<>>;
using mult = binop<std::multiplies<>>;
using expr = boost::variant<int,
recursive_wrapper<add>,
recursive_wrapper<sub>,
recursive_wrapper<mult>>;
template <typename> struct binop { expr left, right; };
} // namespace AST
struct Calculator {
auto operator()(auto const& v) const { return call(v); }
private:
template <typename... T> int call(boost::variant<T...> const& v) const {
return boost::apply_visitor(*this, v);
}
template <typename T>
int call(T const& lit) const { return lit; }
template <typename Op>
int call(AST::binop<Op> const& bin) const {
return Op{}(call(bin.left), call(bin.right));
}
};
int main()
{
using namespace AST;
std::cout << std::boolalpha;
auto sub_expr = add{sub{7, 3}, 8};
expr e1 = sub_expr;
expr e2 = mult{sub_expr, 2};
Calculator calc;
auto result1 = calc(e1);
std::cout << "result1: " << result1 << " Success? " << (12 == result1) << "\n";
// result2 = ((7-3)+8)*2 = 12
auto result2 = calc(e2);
std::cout << "result2: " << result2 << " Success? " << (24 == result2) << "\n";
}
Still prints
result1: 12 Success? true
result2: 24 Success? true

why is specialised template being called?

I created a template called debug which is indirectly invoked through the function errorMsg. I then specialised the template to account for char * (code w/comments below hopefully helps with explanations)
After some playing around I was surprised that even though I defined the template specialisations at a point after they're called in errorMsg(), they were still being used.
I would have assumed because it had not yet been defined at the point the main template would instantiate a default copy or an error would occur
Any help resolving this issue would be great thanks
#include "header.h"
int main()
{
//std::vector<std::string> s_vec{"abc","cede","rfind"};
int i = 3;
int *j = &i;
errorMsg(std::cout,"hey"); //<---calls debug
}
//defined specialisations after its invoked inside errorMsg
template <>
inline std::string debug(char * p)
{
std::cout<<"specialsed char"<<std::endl;
return debug(std::string(p));
}
template <>
inline std::string debug(const char *p)
{
std::cout<<"specialised const char"<<std::endl;
return debug(std::string(p));
(header.h)
#include <iostream>
#include <sstream>
#include <string>
//(1)
template <typename T>
std::string debug(const T&s)
{
std::cout<<"unspecialised obj"<<std::endl;
std::ostringstream oss;
oss<<s;
return oss.str();
}
//(2)
template <typename T>
std::string debug(T *ptr)
{
std::cout<<"unspecialised raw ptr"<<std::endl;
std::ostringstream oss;
oss << "pointer: "<<ptr;
if (ptr)
{
oss<<" "<<debug(*ptr);
}
else
oss<<" null pointer";
return oss.str();
}
template <typename T, typename... Args> void print(std::ostream &os,const T &t,const Args&...rest);
template <typename T> std::ostream &print(std::ostream &os, const T &t);
template <typename... Args>
void errorMsg(std::ostream &os,Args &&...args)
{
print(os,debug(std::forward<Args>(args))...); //debug called here
}
template <typename T>
std::ostream &print(std::ostream &os, const T &t)
{
return os<<t<<std::endl;
}
template <typename T, typename... Args>
void print(std::ostream &os,const T &t,const Args&...rest)
{
os<<t<<", ";
print(os,rest...);
}
result:
specialised const char
unspecialised obj
hey
[temp.expl.spec]/6 If a template, a member template or a member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required.
Your program is ill-formed; no diagnostic required.

Identify pointers in a tuple c++11

I need to convert a tuple to a byte array. This is the code I use to convert to byte array:
template< typename T > std::array< byte, sizeof(T) > get_bytes( const T& multiKeys )
{
std::array< byte, sizeof(T) > byteArr ;
const byte* start = reinterpret_cast< const byte* >(std::addressof(multiKeys) ) ;
const byte* end = start + sizeof(T);
std::copy(start, end, std::begin(byteArr));
return byteArr;
}
Here is how I call it:
void foo(T... keyTypes){
keys = std::tuple<T... >(keyTypes...);
const auto bytes = get_bytes(keys);
}
I need to augment this code such that when a pointer is a part of the tuple, I dereference it to it's value and then pass the new tuple, without any pointers, to the get_bytes() function. How do I detect the presence of a pointer in the tuple? I can then iterate through the tuple and dereference it with:
std::cout << *std::get<2>(keys) << std::endl;
Add a trivial overload: T get_bytes(T const* t) { return getBytes(*t); }.
That would be easy with C++14 :
#include <iostream>
#include <tuple>
#include <utility>
template <class T> decltype(auto) get_dereferenced_value(T &&value) {
return std::forward<T>(value);
}
template <class T> decltype(auto) get_dereferenced_value(T *value) {
return *value;
}
template <class Tuple, class Indexes> struct get_dereferenced_tuple_impl;
template <class... Args, size_t... Index>
struct get_dereferenced_tuple_impl<std::tuple<Args...>,
std::integer_sequence<size_t, Index...>> {
decltype(auto) operator()(std::tuple<Args...> const &originalTuple) {
return std::make_tuple(
get_dereferenced_value(std::get<Index>(originalTuple))...);
}
};
template <class Tuple>
decltype(auto) get_dereferenced_tuple(Tuple const &tupleValue) {
return get_dereferenced_tuple_impl<
Tuple,
std::make_integer_sequence<size_t, std::tuple_size<Tuple>::value>>{}(
tupleValue);
}
int main() {
char c = 'i';
std::tuple<char, char *> t{'h', &c};
auto t2 = get_dereferenced_tuple(t);
std::cout << std::get<0>(t2) << std::get<1>(t2) << "\n";
return 0;
}
If you cannot use C++14, then you would have to write more verbose decltype expressions, as well as include an implementation of std::(make_)integer_sequence.
This has a drawback though : copies will be made before copying the bytes. A tuple of references is not a good idea. The most performant version would be a get_bytes able to serialize the entire mixed tuple directly.

Fusion adaped std_tuple views, conversion to another tuple

Boost Fusion has been designed in such a way that most of the transformations are "lazy", in the sense that they all generate "views" but not actual (Fusion) containers (http://www.boost.org/doc/libs/1_58_0/libs/fusion/doc/html/fusion/algorithm.html). So for example to actually reverse a vector one needs to use the conversion function as_vector (http://www.boost.org/doc/libs/1_58_0/libs/fusion/doc/html/fusion/container/conversion/functions.html).
boost::fusion::vector<int, double, std::string> vec;
auto view_rev = boost::fusion::reverse(vec); // view object
auto vec_rev = boost::fusion::as_vector(view_rev);
Now, I want to do this with adapted std::tuple:
#include<boost/fusion/adapted/std_tuple.hpp>
...
std::tuple<int, double, std::string> tup;
auto view_rev = boost::fusion::reverse(tup);
auto tup_rev = boost::fusion::???(view_rev); // type should be of type std::tuple<std::string, double, int>
How do I convert the resulting view back to a tuple?
I expected this ??? function to be called as_std_tuple (in analogy to boost::fusion::as_vector, but it doesn't exists (yet?).
There a few solutions for reversing tuples, in this case I want just to use what is already in Boost Fusion.
I am not aware of any built-in method to convert a Boost Fusion Sequence into a std::tuple, but using the indices trick it can be implemented rather easily:
template <std::size_t... Is>
struct indices {};
template <std::size_t N, std::size_t... Is>
struct build_indices
: build_indices<N-1, N-1, Is...> {};
template <std::size_t... Is>
struct build_indices<0, Is...> : indices<Is...> {};
template<typename Sequence, std::size_t ...Is>
auto as_std_tuple_impl(const Sequence& s, indices<Is...>&&) -> decltype(std::tie(boost::fusion::at_c<Is>(s)...))
{
return std::tie(boost::fusion::at_c<Is>(s)...);
}
template <typename Sequence, typename Indices = build_indices<boost::fusion::result_of::size<Sequence>::value>>
auto as_std_tuple(const Sequence& s) -> decltype(as_std_tuple_impl(s, Indices()))
{
return as_std_tuple_impl(s, Indices());
}
Here is a full example that reverses an adapted std::tuple using boost::fusion::reverse and converts it back into a std::tuple and prints both tuples:
#include <tuple>
#include <utility>
#include<boost/fusion/adapted/std_tuple.hpp>
#include <boost/fusion/algorithm/transformation/reverse.hpp>
#include <boost/fusion/include/reverse.hpp>
#include <boost/fusion/sequence/intrinsic/size.hpp>
#include <boost/fusion/include/size.hpp>
#include <iostream>
template <std::size_t... Is>
struct indices {};
template <std::size_t N, std::size_t... Is>
struct build_indices
: build_indices<N-1, N-1, Is...> {};
template <std::size_t... Is>
struct build_indices<0, Is...> : indices<Is...> {};
template<typename Sequence, std::size_t ...Is>
auto as_std_tuple_impl(const Sequence& s, indices<Is...>&&) -> decltype(std::tie(boost::fusion::at_c<Is>(s)...))
{
return std::tie(boost::fusion::at_c<Is>(s)...);
}
template <typename Sequence, typename Indices = build_indices<boost::fusion::result_of::size<Sequence>::value>>
auto as_std_tuple(const Sequence& s) -> decltype(as_std_tuple_impl(s, Indices()))
{
return as_std_tuple_impl(s, Indices());
}
template<class Tuple, std::size_t N>
struct TuplePrinter
{
static void print(const Tuple& t)
{
TuplePrinter<Tuple, N-1>::print(t);
std::cout << ", " << std::get<N-1>(t);
}
};
template<class Tuple>
struct TuplePrinter<Tuple, 1>
{
static void print(const Tuple& t)
{
std::cout << std::get<0>(t);
}
};
template<class... Args>
void print(const std::tuple<Args...>& t)
{
std::cout << "(";
TuplePrinter<decltype(t), sizeof...(Args)>::print(t);
std::cout << ")\n";
}
int main()
{
std::tuple<int, double, std::string> tup(1,2.5,"hello");
auto view_rev = boost::fusion::reverse(tup);
auto reversed_tup = as_std_tuple(view_rev);
print(tup);
print(reversed_tup);
return 0;
}
output:
(1, 2.5, hello)
(hello, 2.5, 1)
Live example on ideone

Ambiguous operator<< selection

I have some code which, very much simplified, looks somewhat like this:
#include <iostream>
#include <type_traits>
namespace X {
struct Foo {int x;};
struct Bar {int x;};
template <typename T , typename = typename std::enable_if<
std::is_same<decltype(T::x),int>::value
>::type>
std::ostream & operator<<(std::ostream & os, const T&) {
return os;
}
}
namespace Y {
struct Faa : X::Foo {int y;};
struct Baz {int x; int y;};
template <typename T , typename = typename std::enable_if<
std::is_same<decltype(T::x),int>::value &&
std::is_same<decltype(T::y),int>::value
>::type>
std::ostream & operator<<(std::ostream & os, const T&) {
return os;
}
}
int main() {
// Everything is ok
X::Foo x;
std::cout << x;
Y::Baz k;
std::cout << k;
// Problems..
Y::Faa y;
// std::cout << y; // <--operator is ambiguous
Y::operator<<(std::cout, y);
return 0;
}
Is there any way to avoid the ambiguous operator for Y::Faa and having to manually specify Y::operator<<? If not, why?
Two functions have a conflict because conditions on their arguments have non-empty intersection (actually, 1st supersedes 2nd). Function overloading works only if signatures are different. So, to solve this we have 2 options:
Change conditions so that they have empty intersection (manually forbid having y field by adding && !sfinae_has_member_y<T>::value condition to the 1st enable_if)
template<typename T>
struct sfinae_has_member_y {
static int has(...);
template<typename U = T, typename = decltype(U::y)>
static char has(const U& value);
enum { value = sizeof(char) == sizeof(has(std::declval<T>())) };
};
OR use another C++ feature that supports arguments overlapping, like struct/class template specialization. If you replace bool with int, other fields may be added too:
template<typename T, bool>
struct Outputter {
};
template<typename T>
struct Outputter<T, false> {
static std::ostream & output(std::ostream & os, const T&) {
os << "x";
return os;
}
};
template<typename T>
struct Outputter<T, true> {
static std::ostream & output(std::ostream & os, const T&) {
os << "y";
return os;
}
};
template<typename T, typename = std::enable_if_t<std::is_same<decltype(T::x), int>::value>>
std::ostream & operator<<(std::ostream & os, const T& a) {
return Outputter<T, sfinae_has_member_y<T>::value>::output(os, a);
}

Resources