I'm writing a contains() utility function and have come up with this. My question is: Is there a nicer way to select the right function to handle the call?
template <class Container>
inline auto contains(Container const& c,
typename Container::key_type const& key, int) noexcept(
noexcept(c.end(), c.find(key))) ->
decltype(c.find(key), true)
{
return c.end() != c.find(key);
}
template <class Container>
inline auto contains(Container const& c,
typename Container::value_type const& key, long) noexcept(
noexcept(c.end(), ::std::find(c.begin(), c.end(), key))
)
{
auto const cend(c.cend());
return cend != ::std::find(c.cbegin(), cend, key);
}
template <class Container, typename T>
inline auto contains(Container const& c, T const& key) noexcept(
noexcept(contains(c, key, 0))
)
{
return contains(c, key, 0);
}
For the record, you could write:
#include "magic.h"
template <typename T, typename... Us>
using has_find = decltype(std::declval<T>().find(std::declval<Us>()...));
template <class Container, typename T>
auto contains(const Container& c, const T& key)
{
return static_if<detect<has_find, decltype(c), decltype(key)>{}>
(
[&] (auto& cont) { return cont.end() != cont.find(key); },
[&] (auto& cont) { return cont.end() != std::find(cont.begin(), cont.end(), key); }
)(c);
}
where magic.h contains:
#include <type_traits>
template <bool> struct tag {};
template <typename T, typename F>
auto static_if(tag<true>, T t, F f) { return t; }
template <typename T, typename F>
auto static_if(tag<false>, T t, F f) { return f; }
template <bool B, typename T, typename F>
auto static_if(T t, F f) { return static_if(tag<B>{}, t, f); }
template <bool B, typename T>
auto static_if(T t) { return static_if(tag<B>{}, t, [](auto&&...){}); }
template <typename...>
using void_t = void;
template <typename AlwaysVoid, template <typename...> class Operation, typename... Args>
struct detect_impl : std::false_type {};
template <template <typename...> class Operation, typename... Args>
struct detect_impl<void_t<Operation<Args...>>, Operation, Args...> : std::true_type {};
template <template <typename...> class Operation, typename... Args>
using detect = detect_impl<void, Operation, Args...>;
DEMO
namespace details {
template<template<class...>class Z, class, class...Ts>
struct can_apply:std::false_type{};
template<template<class...>class Z, class...Ts>
struct can_apply<Z,std::void_t<Z<Ts...>>,Ts...>:std::true_type{};
};
template<template<class...>class Z, class...Ts>
using can_apply=typename details::can_apply<Z,void,Ts...>::type;
this takes a template and arguments, and tells you if you can apply it.
template<class T, class...Args>
using dot_find_r = decltype(std::declval<T>().find(std::declval<Args>()...));
template<class T, class...Args>
constexpr can_apply<dot_find_r, T, Args...> can_dot_find{};
we now tag dispatch on myfind:
template<class C>
using iterator = decltype( ::std::begin(std::declval<C>()) );
namespace details {
template<class Container, class Key>
iterator<Container const&> myfind(
std::false_type can_dot_find,
Container const& c,
Key const& key
)
noexcept(
noexcept( ::std::find(::std::begin(c), ::std::end(c), key) )
)
{
return ::std::find( ::std::begin(c), ::std::end(c), key );
}
template <class Container, class Key>
iterator<Container const&> myfind(
std::true_type can_dot_find,
Container const& c,
Key const& key
) noexcept(
noexcept( c.find(key) )
)
{
return c.find(key);
}
}
template<class Container, class Key>
iterator<Container const&> myfind(
Container const& c,
Key const& k
) noexcept (
details::myfind( can_dot_find<Container const&, Key const&>, c, k )
)
{
return details::myfind( can_dot_find<Container const&, Key const&>, c, k );
}
template<class Container, class Key>
bool contains(
Container const& c,
Key const& k
) noexcept (
noexcept( ::std::end(c), myfind( c, k ) )
)
{
return myfind(c, k) != ::std::end(c);
}
As a bonus, the above version works with raw C style arrays.
The next enhancement I'd do would be an auto-ADL std::begin to make begin extensions work in the non-dot_find case.
My personal equivalent returns a std::optional<iterator> of the appropriate type. This both provides a quick "is it there", and gives easy access to the iterator if not not there.
if (auto oit = search_for( container, key )) {
// use *oit here as the iterator to the element, guaranteed not to be `end`
}
or
if (search_for( container, key )) {
// key was there
}
but that is neither here nor there.
So you want to call c.find if possible else std::find. But also being wary of type ambiguity as in std::set.
Here is the code to solve that (with the verbose and micro-optimization removed in favor of readability):
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <type_traits>
#include <set>
#include <cstdarg>
using namespace std;
template <typename T, typename Ret>
struct dummy {
typedef Ret type;
};
template <class Container>
auto contains(const Container &c, typename Container::key_type const &key) ->
typename dummy<decltype(c.find(key)), bool>::type {
cout << "c.find" << endl;
return c.end() != c.find(key);
}
template <class Container, typename ...T>
typename std::enable_if<sizeof...(T)==1, bool>::type contains(const Container &c, const T&... args) {
typename Container::value_type const &val = std::get<0>(std::tuple<const T&...>(args...));
cout << "std::find" << endl;
return c.cend() != find(c.cbegin(), c.cend(), val);
}
int main() {
vector<int> v = {1,2,3};
cout << contains(v,4) << contains(v,2) << endl;
map<int, int> m;
m[1] = 1;
m[2] = 2;
m[3] = 3;
cout << contains(m,4) << contains(m,2) << endl;
set<int> s;
cout << contains(s,4) << contains(s,2) << endl;
return 0;
}
What I did:
I made the first contains function dependent on c.find() being callable. When it's not, the compiler doesn't see the function, and no issues arise
I resolved ambiguity when key_type and value_type are the same, by introducing the function using std::find with its second mandatory argument as a variadic template. I also forced the variadic template of being of size 1.
If you just assume that key_type existing means that container.find exists as in OP, then you can simplify the code and remove the dummy structure:
template <class Container>
bool contains(const Container &c, typename Container::key_type const &key)
{
return c.end() != c.find(key);
}
template <class Container, typename ...T>
typename std::enable_if<sizeof...(T)==1, bool>::type contains(const Container &c, const T&... args) {
typename Container::value_type const &val = std::get<0>(std::tuple<const T&...>(args...));
return c.cend() != find(c.cbegin(), c.cend(), val);
}
Instead of having to resolve ambiguity that way, it's possible to disable the second function altogether if Container::find does exist. This and That answer both show different ways of knowing so. Then using std::enable_if<! (Does Container have the find method?) , bool>::type as the return type of the second function will work.
since find is exist in associative containers then you can explicitly make them as true types.
meta-functions:
template <class> struct has_find_impl:std::false_type{};
template <class T, class... Args> struct has_find_impl<std::set<T, Args...>>:std::true_type{};
template <class T, class... Args> struct has_find_impl<std::map<T, Args...>>:std::true_type{};
template <class T, class... Args> struct has_find_impl<std::multiset<T, Args...>>:std::true_type{};
template <class T, class... Args> struct has_find_impl<std::multimap<T, Args...>>:std::true_type{};
template <class T> using has_find = has_find_impl<typename std::decay<T>::type>;
and use it like so:
template <class Container>
bool contains_impl(const Container& c, const typename Container::key_type& key, std::true_type)
{
return c.find(key) != c.cend();
}
template <class Container>
bool contains_impl(const Container& c, typename Container::const_reference key, std::false_type)
{
return std::find(c.cbegin(), c.cend(), key) != c.cend();
}
template <class Container, class T>
bool contains(const Container& c, const T& key)
{
return contains_impl(c, key, has_find<Container>{});
}
or used it with SFINAE. here a complete example:
#include <iostream>
#include <algorithm>
#include <utility>
#include <map>
#include <set>
#include <vector>
#include <array>
#include <type_traits>
template <class> struct has_find_impl:std::false_type{};
template <class T, class... Args> struct has_find_impl<std::set<T, Args...>>:std::true_type{};
template <class T, class... Args> struct has_find_impl<std::map<T, Args...>>:std::true_type{};
template <class T, class... Args> struct has_find_impl<std::multiset<T, Args...>>:std::true_type{};
template <class T, class... Args> struct has_find_impl<std::multimap<T, Args...>>:std::true_type{};
template <class T> using has_find = has_find_impl<typename std::decay<T>::type>;
template <class Container>
typename std::enable_if<has_find<Container>::value, bool>::type
contains_impl(const Container& c, const typename Container::key_type& key)
{
return c.find(key) != c.cend();
}
template <class Container>
typename std::enable_if<!has_find<Container>::value, bool>::type
contains_impl(const Container& c, typename Container::const_reference key)
{
return std::find(c.cbegin(), c.cend(), key) != c.cend();
}
template <class Container, class T>
bool contains(const Container& c, const T& key)
{
return contains_impl(c, key);
}
int main()
{
std::cout << std::boolalpha;
std::array<int, 3> a = {{ 1, 2, 3 }};
std::cout << contains(a, 0) << "\n";
std::cout << contains(a, 1) << "\n\n";
std::vector<int> v = { 1, 2, 3 };
std::cout << contains(v, 0) << "\n";
std::cout << contains(v, 1) << "\n\n";
std::set<int> s = { 1, 2, 3 };
std::cout << contains(s, 0) << "\n";
std::cout << contains(s, 1) << "\n\n";
std::map<int, int> m = { { 1, 1}, { 2, 2}, { 3, 3} };
std::cout << contains(m, 0) << "\n";
std::cout << contains(m, 1) << "\n\n";
}
Related
I need to make a function take only the first value of every std::pair passed to its arguments. Values passed that are not of type std::pair will be used unaltered. My following solution only works for functions that takes two arguments. I need to know how to generalize this to any number of arguments passed.
#include <type_traits>
template <typename T, typename = void>
struct has_first_type : std::false_type { };
template <typename T>
struct has_first_type<T, std::void_t<typename T::first_type>> : std::true_type { };
template <typename R, typename T, typename U, typename = void> struct act_on_first;
template <typename R, typename T, typename U>
struct act_on_first<R, T, U, std::enable_if_t<has_first_type<T>::value && has_first_type<U>::value>> {
template <typename F>
static R execute (const T& t, const U& u, F f) {
return f(t.first, u.first);
}
};
template <typename R, typename T, typename U>
struct act_on_first<R, T, U, std::enable_if_t<has_first_type<T>::value && !has_first_type<U>::value>> {
template <typename F>
static R execute (const T& t, const U& u, F f) {
return f(t.first, u);
}
};
template <typename R, typename T, typename U>
struct act_on_first<R, T, U, std::enable_if_t<!has_first_type<T>::value && has_first_type<U>::value>> {
template <typename F>
static R execute (const T& t, const U& u, F f) {
return f(t, u.first);
}
};
template <typename R, typename T, typename U>
struct act_on_first<R, T, U, std::enable_if_t<!has_first_type<T>::value && !has_first_type<U>::value>> {
template <typename F>
static R execute (const T& t, const U& u, F f) {
return f(t, u);
}
};
struct foo {
template <typename... Args>
std::size_t operator()(Args&&...) { return sizeof...(Args); } // Simple example only.
};
template <typename T, typename U>
std::size_t bar (const T& t, const U& u) {
return act_on_first<std::size_t, T, U>::execute(t, u, foo());
}
// Testing
#include <iostream>
int main() {
std::pair<int, bool> k = {3, true};
std::pair<int, char> m = {5, 't'};
std::cout << bar(k,m) << '\n'; // 2
std::cout << bar(k,5) << '\n'; // 2
std::cout << bar(3,m) << '\n'; // 2
std::cout << bar(3,5) << '\n'; // 2
}
Write a transformer, that either gives you .first for pairs or just returns its argument:
template <typename T> T const& take_first(T const& x) { return x; }
template <typename T, typename U>
T const& take_first(std::pair<T, U> const& p) { return p.first; }
template <typename... Args>
std::size_t bar(Args const&... args) {
return foo{}(take_first(args)...);
}
I have a tuple of objects of different classes. I want to iterate over the tuple and call a certain method only if those class has one.
For example (pseudo-code):
struct A { int get( ) { return 5; }; };
struct B { };
struct C { int get( ) { return 10; }; };
int i = 0;
tuple<A, B, C> t;
for ( auto t_element : t )
{
if constexpr ( has_get_method( decltype(t_element) ) )
{
i += t_element.get( );
}
}
I already know how to iterate over the tuple and check if a class has some method using sfinae but how do I skip object that do not have the required method?
EDIT:
If you found this old question in the future, please know that this can be done much easier now using concepts from C++20 standard.
Just write a sfinae'd function and a catchall in case the previous one fails. You don't have to use if constexpr for that and you can't use it actually in C++14 (that is how you tagged the question).
Here is a minimal, working example:
#include <tuple>
#include <iostream>
auto value(...) { return 0; }
template <typename T>
auto value(T &t) -> decltype(t.get()) {
return t.get();
}
struct A { int get() { return 5; }; };
struct B {};
struct C { int get() { return 10; }; };
int main() {
int i = 0;
std::tuple<A, B, C> t;
i += value(std::get<0>(t));
i += value(std::get<1>(t));
i += value(std::get<2>(t));
std::cout << i << std::endl;
}
See it up and running on wandbox.
If you have any argument you want to use to test it, you can use std::forward as:
template <typename T, typename... Args>
auto value(T &t, Args&&... args)
-> decltype(t.get(std::forward<Args>(args)...))
{ return t.get(std::forward<Args>(args)...); }
Then invoke it as:
i += value(std::get<0>(t), params);
You can create a type-traits, to check if a class has a get() method, by declaring a couple of functions (no need to define them)
template <typename>
constexpr std::false_type withGetH (long);
template <typename T>
constexpr auto withGetH (int)
-> decltype( std::declval<T>().get(), std::true_type{} );
template <typename T>
using withGet = decltype( withGetH<T>(0) );
The following is a fully working c++17 example
#include <tuple>
#include <iostream>
#include <type_traits>
template <typename>
constexpr std::false_type withGetH (long);
template <typename T>
constexpr auto withGetH (int)
-> decltype( std::declval<T>().get(), std::true_type{} );
template <typename T>
using withGet = decltype( withGetH<T>(0) );
struct A { int get( ) { return 5; }; };
struct B { };
struct C { int get( ) { return 10; }; };
template <typename T>
int addGet (T & t)
{
int ret { 0 };
if constexpr ( withGet<T>{} )
ret += t.get();
return ret;
}
int main ()
{
int i = 0;
std::tuple<A, B, C> t;
i += addGet(std::get<0>(t));
i += addGet(std::get<1>(t));
i += addGet(std::get<2>(t));
std::cout << i << std::endl;
}
If you can't use if constexpr, you can write (in c++11/14) getAdd() as follows, using tag dispatching
template <typename T>
int addGet (T & t, std::true_type const &)
{ return t.get(); }
template <typename T>
int addGet (T & t, std::false_type const &)
{ return 0; }
template <typename T>
int addGet (T & t)
{ return addGet(t, withGet<T>{}); }
--EDIT--
The OP ask
my code needs to check for a templated method with parameters. Is it possible to modify your solution so that instead of int get() it could check for something like template<class T, class U> void process(T& t, U& u)?
I suppose it's possible.
You can create a type-traits withProcess2 (where 2 is the number of arguments) that receive three template type parameters: the class and the two template types
template <typename, typename, typename>
constexpr std::false_type withProcess2H (long);
template <typename T, typename U, typename V>
constexpr auto withProcess2H (int)
-> decltype( std::declval<T>().process(std::declval<U>(),
std::declval<V>()),
std::true_type{} );
template <typename T, typename U, typename V>
using withProcess2 = decltype( withProcess2H<T, U, V>(0) );
The following is a fully working example (c++17, but now you know how to make it c++14) with A and C with a process() with 2 template parameters and B with a process() with only 1 template parameter.
#include <iostream>
#include <type_traits>
template <typename, typename, typename>
constexpr std::false_type withProcess2H (long);
template <typename T, typename U, typename V>
constexpr auto withProcess2H (int)
-> decltype( std::declval<T>().process(std::declval<U>(),
std::declval<V>()),
std::true_type{} );
template <typename T, typename U, typename V>
using withProcess2 = decltype( withProcess2H<T, U, V>(0) );
struct A
{
template <typename T, typename U>
void process(T const &, U const &)
{ std::cout << "A::process(T, U)" << std::endl; }
};
struct B
{
template <typename T>
void process(T const &)
{ std::cout << "B::process(T)" << std::endl; }
};
struct C
{
template <typename T, typename U>
void process(T &, U &)
{ std::cout << "C::process(T, U)" << std::endl; }
};
template <typename T>
void callProcess (T & t)
{
static int i0 { 0 };
static long l0 { 0L };
if constexpr ( withProcess2<T, int &, long &>{} )
t.process(i0, l0);
}
int main ()
{
std::tuple<A, B, C> t;
callProcess(std::get<0>(t)); // print A::process(T, U)
callProcess(std::get<1>(t)); // no print at all
callProcess(std::get<2>(t)); // print C::process(T, U)
}
I want to have two overloads of a template function but have one take precedence. I am trying to define a size() function that uses the size member function if available but falls back to using std::begin() and std::end() (This is needed for say std::forward_list()). This is what they look like:
template <class Container>
constexpr auto size(const Container& cont) -> decltype (cont.size())
{
return cont.size();
}
template <class Container>
auto size(const Container& cont) -> decltype (
std::distance(std::begin(cont), std::end(cont)))
{
return std::distance(std::begin(cont), std::end(cont));
}
The problem is that the compiler can't decide which overload to use for containers with a size() and a begin()/end(). How do I make it choose the first implementation when possible? (I know SFINAE is part of the solution, but I am not knowledgeable enough in the arcane arts to figure it out)
Also (unrelated), is there an easier way to declare the return type for the second function?
Yet another one, with bog-standard overload resolution as the tiebreaker:
namespace details {
template <class Container>
constexpr auto size(const Container& cont, int) -> decltype (cont.size())
{
return cont.size();
}
template <class Container>
auto size(const Container& cont, ...) -> decltype (
std::distance(std::begin(cont), std::end(cont)))
{
return std::distance(std::begin(cont), std::end(cont));
}
}
template <class Container>
auto size(const Container& cont) -> decltype(details::size(cont, 0)) {
return details::size(cont, 0);
}
You'd create a traits specifying if there is a size() function. You then use std::enable_if with that trait and selectively enable the function you prefer to be chosen, disabling the respective other.
This should do the trick:
struct has_size_aux {
template <typename S>
static char (&test(decltype(std::declval<S>().size())*))[1];
template <typename S>
static char (&test(...))[2];
};
template <typename T>
struct has_size
: std::integral_constant<bool, 1 == sizeof(has_size_aux::test<T>(nullptr))> {
};
template <class Container, typename = std::enable_if_t<has_size<Container>::value>>
constexpr auto size(const Container& cont)
-> decltype (cont.size())
{
return cont.size();
}
template <class Container, typename = std::enable_if_t<!has_size<Container>::value>>
auto size(const Container& cont) ->
decltype (std::distance(std::begin(cont), std::end(cont)))
{
return std::distance(std::begin(cont), std::end(cont));
}
Another answer using tag dispatch instead:
#include <vector>
#include <forward_list>
#include <iostream>
#include <cstdint>
template <typename Container>
std::true_type size_type(Container&& c, decltype(c.size()));
template <typename Container>
std::false_type size_type(Container&& c, ...);
template <typename Container>
auto size(Container&& c, std::true_type) {
return c.size();
}
template <typename Container>
auto size(Container&& c, std::false_type) {
using std::begin;
using std::end;
return std::distance(begin(c), end(c));
}
template <typename Container>
auto size(Container&& c) {
using type = decltype(size_type(std::forward<Container>(c), 0));
return size(std::forward<Container>(c), type {});
}
template <typename T, size_t N>
constexpr size_t size(T const (&)[N]) {
return N;
}
int main() {
int const arr[10] {};
std::forward_list<int> const list {1, 3, 5};
std::vector<int> const v {2, 4};
std::cout << size(arr) << ", " << size(list) << ", " << size(v);
}
I have the following code:
#include <array>
#include <iostream>
#include <typeinfo>
#include <type_traits>
#include <utility>
namespace impl
{
template <typename T>
struct Matrix_traits {
};
}
template <size_t M, size_t N, typename T>
class Matrix
{
};
template <size_t M, size_t N, typename T>
struct impl::Matrix_traits<Matrix<M, N, T>> {
template <typename U>
struct scalar_mult_type
{
// just for testing
using type = std::pair<std::array<T, M>, std::array<T, N>>;
};
};
int main()
{
Matrix<3, 4, char> m;
mult(3, m);
return 0;
}
When I use the following function implementation, where I'm explicitly specifying the return type:
template <typename T, typename U>
std::pair<std::array<char, 3>, std::array<char, 4>> mult(const T& lambda, const U& m)
{
typename impl::Matrix_traits<U>::scalar_mult_type<T>::type result;
std::cout << typeid(result).name() << "\tEUREKA!\n";
return result;
}
It works... but this is obviously not what I want... but when I'm trying to be more flexible:
template <typename T, typename U>
typename impl::Matrix_traits<U>::scalar_mult_type<T>::type mult(const T& lambda, const U& m)
{
typename impl::Matrix_traits<U>::scalar_mult_type<T>::type result;
std::cout << typeid(result).name() << "\tEUREKA!\n";
return result;
}
I have "unrecognizable template declaration/definition" error.
It's a real puzzle to me. Why the same declaration works for local variable 'result' but fails as the return type?
template are missing, it should be
template <typename T, typename U>
typename impl::Matrix_traits<U>::template scalar_mult_type<T>::type
mult(const T& , const U& )
{
typename impl::Matrix_traits<U>::template scalar_mult_type<T>::type result;
std::cout << typeid(result).name() << "\tEUREKA!\n";
return result;
}
Demo
I need a variant of the popular indices trick, that does a Cartesian product of 2 sequences of indices of possibly different lengths. Can you give hints/examples on how this might be done? Perhaps a link to a library.
EDIT: I could only come up with this:
template <typename ...T> struct list {};
template <typename T, typename U>
struct pair
{
typedef T first;
typedef U second;
};
template <std::size_t i>
using index = std::integral_constant<std::size_t, i>;
template <std::size_t ON, std::size_t M, std::size_t N, typename ...Ps>
struct cartesian
: std::conditional<bool(N),
cartesian<ON, M, N - 1, pair<index<M>, index<N> >, Ps...>,
cartesian<ON, M - 1, ON, pair<index<M>, index<N> >, Ps...>
>::type
{
};
template <std::size_t ON, typename ...Ps>
struct cartesian<ON, 0, 0, Ps...>
: list<pair<index<0>, index<0> >, Ps...>
{
};
template <std::size_t M, std::size_t N>
struct make_cartesian : cartesian<N - 1, M - 1, N - 1>
{
static_assert(M > 0, "M has to be greater than 0");
static_assert(N > 0, "N has to be greater than 0");
};
Here's a rather straightforward and boring implementation.
#include <cstdlib>
#include <iostream>
namespace ct {
template <typename, typename>
struct pair {};
template <typename... a>
struct list {};
template <typename a, typename... b>
struct cons_t;
template <typename a>
struct cons_t<a, list<>>
{
using type = list<a>;
};
template <typename a, typename bh, typename... bt>
struct cons_t<a, list<bh, bt...>>
{
using type = list<a, bh, bt...>;
};
template <typename a, typename... b>
struct concat_t;
template <typename b>
struct concat_t<list<>, b>
{
using type = b;
};
template <typename b, typename ah, typename... at>
struct concat_t<list<ah, at...>, b>
{
using type = typename cons_t<ah, typename concat_t<list<at...>, b>::type>::type;
};
template <typename a, typename b>
using cons = typename cons_t<a,b>::type;
template <typename a, typename b>
using concat = typename concat_t<a,b>::type;
template <typename a, typename b>
struct cartesian1;
template <typename a>
struct cartesian1<a, list<>>
{
using type = list<>;
};
template <typename a, typename bh, typename... bt>
struct cartesian1<a, list<bh, bt...>>
{
using type = cons<pair<a, bh>, typename cartesian1<a, list<bt...>>::type>;
};
template <typename a, typename b>
struct cartesian_t;
template <typename a>
struct cartesian_t<list<>, a>
{
using type = list<>;
};
template <typename ah, typename b, typename... at>
struct cartesian_t<list<ah, at...>, b>
{
using type = concat<typename cartesian1<ah, b>::type,
typename cartesian_t<list<at...>, b>::type>;
};
template <typename a, typename b>
using cartesian = typename cartesian_t<a,b>::type;
template <size_t x>
struct val {};
template <size_t... a>
struct vlist {};
template <typename t>
struct vlist2list_t;
template <>
struct vlist2list_t<vlist<>>
{
using type = list<>;
};
template <size_t ah, size_t... at>
struct vlist2list_t<vlist<ah, at...>>
{
using type = cons<val<ah>, typename vlist2list_t<vlist<at...>>::type>;
};
template <typename a>
using vlist2list = typename vlist2list_t<a>::type;
template <size_t...a>
using vl = vlist2list<vlist<a...>>;
template<size_t x1, size_t x2>
std::ostream& operator<< (std::ostream& s,
pair<val<x1>, val<x2>> z)
{
s << "(" << x1 << "," << x2 << ")";
return s;
}
std::ostream& operator<< (std::ostream& s,
list<> z)
{
s << "[]";
}
template <typename ah, typename... at>
std::ostream& operator<< (std::ostream& s,
list<ah, at...> z)
{
s << ah() << ":" << list<at...>();
}
}
int main ()
{
using a = ct::cartesian<ct::vl<1,2,3>, ct::vl<4,5,6>>;
std::cout << a() << std::endl;
}
Sorry for the mistake. I meant:
template<class InIter, class OutIter>
OutIter cartesian_product(InIter first1, InIter last1, InIter first2, InIter last2,
OutIter output) {
for (auto It1 = first1 ; It1 != last1; ++It1)
for (auto It2 = first2; It2 != last2; ++It2)
*output++ = *It1 * *It2;
}