Query number of arguments from a lambda/function - c++

I would like to query a lambda/function about how much parameters it uses.
Small (pseudo) example code:
template <class InputIterator, class Predicate>
bool visitAll( InputIterator f, InputIterator l, Predicate p, UserData* d=nullptr)
{
for(; f != l; ++f)
{
if(number_of_arguments(p) == 1)
{
if(!p(*f))
return false;
}
else
{
if(!p(*f, *d))
return false;
}
}
}
Note that the function I am asking for is number_of_arguments(...).
I have been searching in the Closure and std::function reference, but did not find a clue about a solution.
Thanks for your help!

Obviously the code as you posted does not make much sense, as anyway either p(*f) or p(*f, *d) would fail to compile. Therefore you need to split this into two templates, and then you can test the number of arguments of Predicate using a rather straightforward SFINAE approach:
template <class InputIterator, class Predicate>
bool visitAll( InputIterator f, InputIterator l, Predicate p, UserData* d=nullptr,
decltype(declval<Predicate>()(*declval<InputIterator>()),1) unused = 1)
{
cout << "1" << std::endl;
for(; f != l; ++f)
{
if(!p(*f))
return false;
}
return true;
}
template <class InputIterator, class Predicate>
bool visitAll( InputIterator f, InputIterator l, Predicate p, UserData* d=nullptr,
decltype(declval<Predicate>()(*declval<InputIterator>(), declval<UserData>()),1) unused = 1)
{
cout << "2" << std::endl;
for(; f != l; ++f)
{
if(!p(*f, *d))
return false;
}
return true;
}
Usage:
std::vector<int> a{1,2};
const auto t = [](int x){ return 1;};
const auto t2 = [](int x, UserData y){ return 1;};
UserData d;
visitAll(a.begin(), a.end(), t);
visitAll(a.begin(), a.end(), t2, &d);
Of course, you can use std::bind to avoid code duplication by calling first version from the second.
Another approach is to use code similar to how std::bind checks that it got needed number of arguments:
template<typename _Func>
struct noa_helper {
};
template<typename _Ret, typename... _Args>
struct noa_helper<_Ret (*)(_Args...)> {
static int noa() { return sizeof...(_Args); }
};
template<class F>
int number_of_arguments(F f) {
return noa_helper<typename std::decay<F>::type>::noa();
}
void foo();
int bar(int x, int y);
...
std::cout << number_of_arguments(foo) << std::endl; // prints 0
std::cout << number_of_arguments(bar) << std::endl; // prints 2
This works only for real functions, not lambdas, nor std::function, though probably some more template magic can make it work for the latter two categories.

Related

Using C++ generic programming to do runtime call of func(x,y) for all permutations of x and y types

env->CallObjectMethod(hashMapInstance, put, _, _)
I want to call this function with all the possible permutations of std::string, int, double on the underscores. For example:
env->CallObjectMethod(hashMapInstance, put, myString, myInt)
env->CallObjectMethod(hashMapInstance, put, myInt, myDouble)
env->CallObjectMethod(hashMapInstance, put, myInt, myInt)
//...
Of course I can do this with nested ifs but I'd be reusing the same code on lots of places. Ideally I'd like a way to receive a std::map<JavaObject, JavaObject> myMap and then for each pair on the map, do the following:
for (auto pair : myMap)
if (pair.first.type == JavaObject::String && pair.second.type == JavaObject::Integer)
env->CallObjectMethod(hashMapInstance, put, pair.first.getString(), pair.second.getInt())
//OR
if (pair.first.type == JavaObject::Integer && pair.second.type == JavaObject::Integer)
env->CallObjectMethod(hashMapInstance, put, pair.first.getInt(), pair.second.getInt()) //
//OR
if (pair.first.type == JavaObject::Double && pair.second.type == JavaObject::String)
env->CallObjectMethod(hashMapInstance, put, pair.first.getDouble(), pair.second.getString())
//...
as you can see, I need a way to efficiently be able to call each permutation env->CallObjectMethod(hashMapInstance, put, _, _) for every possible permutation of JavaObject, JavaObject received (JavaObject is just a class that can hold string, int, double and possibly more in the future)
The first thing I thought was to create a templated function:
template<typename T, typename V>
void myCallobjectMethod(env, jobject instance, jmethodID method, T obj1, V obj2)
But I still have to read JavaObject.type for the first item and then inside this if, do another if for the second part, just to call my templated function, so I'm still with the same problem.
I thought of another way, in pseudocode:
using namespace std::placeholders;
for (auto pair : myMap)
auto bind1 = std::bind(env->CallObjectMethod, hashMapInstance, put, _3, _4); //binds the hashMapInstance and put
auto bind2 = std::bind(bind1, pair.first, _2); //binds the first object
auto bind3 = std::bind(bin2, pair.second); //binds the second object
bind3(); //now I can call bind3 to execute the call
but it's not that simple, I don't even know what's happening to the types of things here.
JavaObject is a sum type, so it should have a visit function:
template<class F> auto visit(F&& f, JavaObject const& o) {
switch (o.type) {
case JavaObject::String : return f(o.getString());
case JavaObject::Integer : return f(o.getInt());
case JavaObject::Double : return f(o.getDouble());
}
}
Any unary visit function can be composed with itself to operate on 2 arguments:
template<class F> auto visit(F&& f, JavaObject const& o1, JavaObject const& o2) {
return visit([&](auto const& x1) {
return visit([&](auto const& x2) {
return f(x1, x2); }, o2); }, o1);
}
Now you can write:
visit([&](auto const& x1, auto const& x2) {
env->CallObjectMethod(hashMapInstance, put, x1, x2);
}, pair.first, pair.second);
Extending visit to arbitrary arity is left as an exercise for the reader (Hint: use recursion).
In addition to ecatmur's answer, I am going to give some hint on how to do the permutation:
#include <functional>
#include <iostream>
#include <tuple>
void test(int a, int b, int c, int d, int e, int f, int g) {
std::cout << a << " " << b << " " << c << " " << d << " " << e << " " << f << " " << g << std::endl;
}
template <typename ReturnT, typename T, typename U, typename ... TRestArgs>
auto easy_bind(std::function<ReturnT(T, TRestArgs...)> func, U&& arg) -> std::function<ReturnT(TRestArgs...)> {
if constexpr (std::is_same_v<void, ReturnT>) {
return [=](TRestArgs... args) { func(arg, args...); };
}
else {
return [=](TRestArgs... args) { return func(arg, args...); };
}
}
template <typename CallableT, typename ... TArgs, std::size_t ... SeqLeft, std::size_t ... SeqRight>
void permute_call_impl(CallableT func, std::tuple<TArgs...> args, std::index_sequence<SeqLeft...>, std::index_sequence<SeqRight...>);
template <typename CallableT, typename ... TArgs, std::size_t ... Seq>
void permute_call_splitter(CallableT func, std::tuple<TArgs...> args, std::index_sequence<Seq...>);
template <typename CallableT, typename ... TArgs, std::size_t ... SeqLeft, std::size_t ... SeqRight>
void permute_call_impl(CallableT func, std::tuple<TArgs...> args, std::index_sequence<SeqLeft...>, std::index_sequence<SeqRight...>) {
if constexpr (sizeof...(SeqLeft) + sizeof...(SeqRight) == 0u) {
func();
}
else {
permute_call_splitter(func,
std::make_tuple(std::get<SeqLeft>(args)..., std::get<SeqRight + sizeof...(SeqLeft) + 1>(args)...),
std::make_index_sequence<sizeof...(SeqLeft) + sizeof...(SeqRight)>{}
);
}
}
template <typename CallableT, typename ... TArgs, std::size_t ... Seq>
void permute_call_splitter(CallableT func, std::tuple<TArgs...> args, std::index_sequence<Seq...>) {
constexpr auto size = sizeof...(Seq);
(permute_call_impl(easy_bind(func, std::get<Seq>(args)),
args,
std::make_index_sequence<Seq>{},
std::make_index_sequence<size - 1u - Seq>{}
), ...);
}
template <typename CallableT, typename ... TArgs>
void permute_call(CallableT func, TArgs... args) {
permute_call_splitter(func, std::make_tuple(args...), std::make_index_sequence<sizeof...(TArgs)>{});
}
int main() {
std::function func = test;
permute_call(func, 1, 2, 3, 4, 5, 6, 7);
return 0;
}
So basically you have a std::index_sequence, you iterate on every index, remove the element, merge the rest two parts, and pass it to the next level of recursion.
I did not take care of reference forwarding in this example, for now. But it would gives you a rough idea about how things should work.
Live Example

Can a function be applied to the value of a std::optional, getting back an optional?

I think that applying a function to an optional is a really useful pattern. It is however cumbersome to do with the C++ STL. For example:
std::optional<Vector3D> vec = tryCreateVector();
std::optional<float> length =
vec.has_value() ? std::optional<float>(vec->length()) : std::nullopt;
Is there an equivalent of haskell's fmap or rust's Option::map in C++? Something like the following:
std::optional<Vector3D> vec = tryCreateVector();
std::optional<float> length = map(vec, [](auto vec) { return vec.length(); });
You could define the following function:
namespace detail
{
template<typename Callable, typename T>
struct apply_helper
{
using T_noref = typename std::remove_reference<T>::type;
using value_type = typename T_noref::value_type;
using Callable_return = decltype(std::declval<Callable>()(std::declval<value_type>()));
using return_type = optional<Callable_return>;
static return_type eval(Callable&& f, T&& val)
{
if(val)
{
return apply(std::forward<Callable&&>(f), *val);
}
else return boost::none;
}
private:
static Callable_return apply(Callable&& f, value_type& v)
{
return f(v);
}
static Callable_return apply(Callable&& f, value_type const& v)
{
return f(v);
}
static Callable_return apply(Callable&& f, value_type&& v)
{
return f(v);
}
};
}
template<typename Callable, typename T>
optional<decltype(std::declval<Callable>()(std::declval<T>()))> apply(Callable&& f, optional<T> const& a)
{
return detail::apply_helper<Callable, optional<T> const&>::eval(std::forward<Callable>(f), a);
}
which could then be used like:
optional<int> foo(optional<int> value)
{
auto f = [](int v){return v + 10;};
return apply(f, value);
}
As far as I know standard library does not provide such functionality out of the box. It is fairly easy to implement it though.
#include <optional>
#include <iostream>
#include <functional>
std::optional<int> create_an_int()
{
return 1;
}
std::optional<int> dont_create_an_int()
{
return {};
}
template<typename T, typename F>
auto handler_wrapper(const std::optional<T>& in, F h)
{
return in.has_value() ? std::optional{h(*in)} : std::nullopt;
}
int main()
{
auto handler = [](const int& in){ return 3*in; };
auto test = create_an_int();
auto multiplied = handler_wrapper(test, handler);
std::cout << *multiplied << std::endl;
test = dont_create_an_int();
auto nulled = handler_wrapper(test, handler);
if (!nulled.has_value())
std::cout << "null optional" << std::endl;
}
Basically all you need to do is to create a template wrapper accepting any callable and an optional and you are done (note: the snippet above is not the prettiest / best implementation, but should give you a good starting point I guess).
The code above will obviously produce "3" and "null optional" as output.

Cartesian Product using Iterators and Variadic Templates

I'm trying to create a function to generate the Cartesian product of a variable number of input ranges, using the style of the STL. My basic format is that the function accepts a fixed range and the start of an output range, then a variadic number of bidirectional input iterators.
template <
typename BidirectionalIterator,
typename OutputIterator,
typename... Args
>
void cartesian_product(
BidirectionalIterator first,
BidirectionalIterator last,
OutputIterator result,
Args&&... args
);
My idea for the args is that I make a tuple out of it, then I iterate through that tuple to extract the elements. This would require me to follow a few basic steps:
Make a tuple from args
Dereference each iterator in the newly created tuple
Increment each iterator in the tuple in sequence, so that we get all possible combinations of the values in the ranges.
To elaborate on step 3: if we had two sets A = {0, 1} and B = {2, 3}, the Cartesian product A x B = {(0, 2), (0, 3), (1, 2), (1, 3)}.
I can do the first step like:
auto arg_tuple = std::make_tuple(std::forward<Args>(args)...);
The second step, I'm not too sure about. I think I will have somehow push_back elements to a temporary tuple, then set *result equal to that temporary tuple. I was a little inspired by the way that ostream accomplishes this, so I think this could come in handy:
template <typename Tuple, typename T>
auto operator<<(const Tuple &lhs, const T &rhs)
-> decltype(std::tuple_cat(lhs, std::make_tuple(rhs)))
{
return std::tuple_cat(lhs, std::make_tuple(rhs));
}
The third step is probably pretty trivial. I could combine something like this:
template <typename T>
auto pre_increment(T &x) -> decltype(++x) {
return ++x;
}
with one of the 3,000 implementations of for_each for a tuple that are on here.
Odds are that I'm not correctly leveraging C++14 for this. My education has been entirely on the less-difficult parts of C++11 so far.
If you're tempted to recommend I use boost::fusion for this, thanks, but I would prefer to not use it.
In C++17, we get std::apply(). A possible C++14 implementation is found on that link. We can then implement fmap for a tuple as:
template <class Tuple, class F>
auto fmap(Tuple&& tuple, F f) {
return apply([=](auto&&... args){
return std::forward_as_tuple(f(std::forward<decltype(args)>(args))...);
}, std::forward<Tuple>(tuple));
}
With that:
auto deref_all = fmap(iterators, [](auto it) -> decltype(auto) { return *it; });
auto incr_all = fmap(iterators, [](auto it) { return ++it; });
Here's what I've come up with:
#include <iostream>
#include <tuple>
#include <vector>
template <typename T, typename B>
bool increment(const B& begins, std::pair<T,T>& r) {
++r.first;
if (r.first == r.second) return true;
return false;
}
template <typename T, typename... TT, typename B>
bool increment(const B& begins, std::pair<T,T>& r, std::pair<TT,TT>&... rr) {
++r.first;
if (r.first == r.second) {
r.first = std::get<std::tuple_size<B>::value-sizeof...(rr)-1>(begins);
return increment(begins,rr...);
}
return false;
}
template <typename OutputIterator, typename... Iter>
void cartesian_product(
OutputIterator out,
std::pair<Iter,Iter>... ranges
) {
const auto begins = std::make_tuple(ranges.first...);
for (;;) {
out = { *ranges.first... };
if (increment(begins, ranges...)) break;
}
}
struct foo {
int i;
char c;
float f;
};
int main(int argc, char* argv[]) {
std::vector<int> ints { 1, 2, 3 };
std::vector<char> chars { 'a', 'b', 'c' };
std::vector<float> floats { 1.1, 2.2, 3.3 };
std::vector<foo> product;
cartesian_product(
std::back_inserter(product),
std::make_pair(ints.begin(), ints.end()),
std::make_pair(chars.begin(), chars.end()),
std::make_pair(floats.begin(), floats.end())
);
for (const auto& x : product)
std::cout << x.i << ' ' << x.c << ' ' << x.f << std::endl;
}
The cartesian_product function has a slightly different signature than yours, but it should be straightforward to write a wrapper.
Since the ranges you pass in may potentially have different extents, I'd suggest you pass both begin and end, as in my example.
I recently came up with the solution that allows to invoke a callable object (e.g., lambda) for any combination of the Cartesian product of the input ranges defined by iterators. The lambda makes elements of input ranges accessible by values or by references. Exemplary usage:
std::vector<int> vector = { 1, 2, 3 };
std::set<double> set = { -1.0, -2.0 };
std::string string = "abcd";
bool array[] = { true, false };
std::cout << std::boolalpha;
cartesian_product([](const auto& v1, const auto& v2, const auto& v3, const auto& v4){
std::cout << "(" << v1 << ", " << v2 << ", " << v3 << ", " << v4 << ")\n";
},
std::begin(vector), std::end(vector),
std::begin(set), std::end(set),
std::begin(string), std::end(string),
std::begin(array), std::end(array)
);
I haven't found a solution with such a (natural) syntax (the style of the STL you ask for). The cartesian_product function is in my case built upon C++17 std::apply as follows:
template <typename F, typename... Ts>
void cartesian_product_helper(F&& f, std::tuple<Ts...> t) { std::apply(f, t); }
template <typename F, typename... Ts, typename Iter, typename... TailIters>
void cartesian_product_helper(
F&& f, std::tuple<Ts...> t, Iter b, Iter e, TailIters... tail_iters)
{
for (auto iter = b; iter != e; ++iter)
cartesian_product_helper(
std::forward<F>(f), std::tuple_cat(t, std::tie(*iter)), tail_iters...);
}
template <typename F, typename... Iters>
void cartesian_product(F&& f, Iters... iters) {
cartesian_product_helper(std::forward<F>(f), std::make_tuple(), iters...);
}
It's relatively simple - it iterates over all ranges recursively and in each iteration, it appends the reference to the corresponding dereferenced iterator (i.e., range item) to the tuple. When the tuple is complete (has references to items from all levels), then the callable object is invoked and those references from the tuple are used as arguments.
Just I'm not sure whether this is the most efficient way, so any suggestions for improvement would be helpful.
Live demo is here: https://wandbox.org/permlink/lgPlpKXRkPuTtqo8

Adapting a function that returns std::future<T> to std::future<U>

Suppose I have an asynchronous functional map primitive which takes a std::vector as input and returns a std::future to a Container of my choice as output:
template<class Container, class T, class Function>
std::future<Container> async_map(const std::vector<T>& in, Function f)
{
return std::async([=]
{
Container result(in.size());
for(size_t i = 0; i < in.size(); ++i)
{
result[i] = f(in[i]);
}
return result;
});
}
I'd like to build an analogous async_for_each function by adapting async_map:
template<class T, class Function>
std::future<void> async_for_each(const std::vector<T>& in, Function f);
The problem is that async_for_each returns std::future<void>, while async_map returns std::future<Container>, and void is not a Container.
I can get something close to what I want by constructing a type which fulfills the Container requirements but ignores assignments to it (empty_container in my initial attempt), but a std::future of this type is still not std::future<void>.
I have the following constraints on my solution:
There must be only one implementation of async_map, with the given function signature (i.e., no async_map<void> specialization)
There must be only one std::future created (i.e., no .then()-style continuation)
I was hoping there is an efficient way to convert between std::futures of related types (or cast a std::future<T> to std::future<void>), but the answer to this question suggests it is not possible.
Random ideas:
Can async_for_each wrap its function in a clever way to solve this problem?
Can the type used for Container act like void in async_for_each, but act like Container in async_map?
My initial attempt is below. Is it possible to build what I want given these constraints?
#include <future>
#include <vector>
#include <iostream>
template<class Container, class T, class Function>
std::future<Container> async_map(const std::vector<T>& in, Function f)
{
return std::async([=]
{
Container result(in.size());
for(size_t i = 0; i < in.size(); ++i)
{
result[i] = f(in[i]);
}
return result;
});
}
struct empty_container
{
empty_container(size_t) {}
struct empty
{
template<class T>
empty operator=(const T&) const { return empty(); }
};
empty operator[](size_t) { return empty(); }
};
template<class Function>
struct invoke_and_ignore_result
{
Function f;
template<class T>
empty_container::empty operator()(T&& x) const
{
f(std::forward<T>(x));
return empty_container::empty();
}
};
template<class T, class Function>
//std::future<void> async_for_each(const std::vector<T>& in, Function f)
std::future<empty_container> async_for_each(const std::vector<T>& in, Function f)
{
invoke_and_ignore_result<Function> g{f};
std::future<empty_container> f1 = async_map<empty_container>(in, g);
return f1;
}
int main()
{
std::vector<int> vec(5, 13);
async_for_each(vec, [](int x)
{
std::cout << x << " ";
}).wait();
std::cout << std::endl;
return 0;
}
I think you are using the wrong primitive.
Here I build everything up with a different primitive -- a sink.
A sink can consume data via operator()(T&&)&. It then returns some result via operator()()&&.
Here is a async_sink function:
template<class Container, class Sink>
std::future<std::result_of_t<std::decay_t<Sink>()>>
async_sink(Container&& c, Sink&& sink)
{
return std::async(
[c=std::forward<Container>(c), sink=std::forward<Sink>(sink)]
{
for( auto&& x : std::move(c) ) {
sink( x );
}
return std::move(sink)();
});
}
Here is an implementation of a sink that puts things into a container, then returns it:
template<class C>
struct container_sink_t {
C c;
template<class T>
void operator()( T&& t ){
c.emplace_back( std::forward<T>(t) );
}
C operator()()&&{
return std::move(c);
}
};
Here is a sink that takes a function and a sink and composes them:
template<class F, class S>
struct compose_sink_t {
F f;
S s;
template<class T>
void operator()(T&& t){
s(
f(std::forward<T>(t))
);
}
std::result_of_t<S()> operator()()&&{
return std::move(s)();
}
};
template<class C, class F>
compose_sink_t<std::decay_t<F>, container_sink_t<C>>
transform_then_container_sink( F&& f ) {
return {std::forward<F>(f)};
}
Here is a sink that takes a function, calls it, and returns void:
template<class F>
struct void_sink_t {
F f;
template<class T>
void operator()(T&& t)
{
f(std::forward<T>(t));
}
void operator()() {}
};
template<class F>
void_sink_t<std::decay_t<F>> void_sink(F&&f){return {std::forward<F>(f)}; }
now your map is:
template<class Container, class T, class Function>
std::future<Container> async_map(const std::vector<T>& in, Function f)
{
return async_sink(
in,
transform_then_container_sink<Container>(std::forward<F>(f))
);
}
and your for_each is:
template<class T, class Function>
std::future<void> async_for_each(const std::vector<T>& in, Function f)
{
return async_sink(
in,
void_sink(std::forward<F>(f))
);
}
I freely use C++14 features, because they made the code better. You can replace the move-into-container with a copy for a touch less efficiency, and write your own _t aliases.
The above code has not been tested or run, so there are probably bugs in it. There is one issue I'm uncertain of -- can a lambda returning void end with a return void_func() in that context? -- but as that uglyness is in one spot, it can be worked around even if it doesn't work.

C++: Is there a way to define a static array inline?

I would like to define a simple template function which takes a runtime value and determines if it is a member of some set of possible values.
Usage:
int x; // <- pretend this came from elsewhere...
if (isoneof(x, {5,3,9,25}) ...
Something like:
template <typename T, size_t size>
bool isoneof(T value, T (&arr)[size])
{
for (size_t i = 0; i < size; ++i)
if (value == arr[i])
return true;
return false;
}
I assume that this is doomed to failure, as I don't see how one can create a static array inline.
I can use:
int kPossibilities[] = {5,3,9,25};
if (isoneodf(6, kPossibilities)) ...
With a minor change to isoneof:
template <typename T1, typename T2, size_t size>
bool isoneof(T1 value, const T2 (&arr)[size])
{
for (size_t i = 0; i < size; ++i)
if (value == arr[i])
return true;
return false;
}
Which also makes it a tad more flexible.
Does anyone have an improvement to offer? A better way to define a "set of static values inline"?
If you like such things, then you will be a very happy user of Boost.Assign.
Boost.Assign actually proves that such semantics are possible, however one look at the source of assign will convince you that you don't want to do that by yourself :)
You will be able to create something like this however:
if (isoneof(x, list_of(2)(3)(5)(7)(11)) { ...
... the downside being you'd have to use boost::array as the parameter instead of a built-in array (thanks, Manuel) -- however, that's a nice moment to actually start using them :>
It's possible in the next C++ standard.
Up till then, you can work around it by e.g. overloading operator, for a static object that starts a static array.
Note: this implementation is O(n^2) and may be optimized - it's just to get the idea.
using namespace std;
template< typename T, size_t N >
struct CHead {
T values[N];
template< typename T > CHead<T,N+1> operator,( T t ) {
CHead<T,N+1> newhead;
copy( values, values+N, newhead.values);
newhead.values[N]=t;
return newhead;
}
bool contains( T t ) const {
return find( values, values+N, t ) != values+N;
}
};
struct CHeadProto {
template< typename T >
CHead<T,1> operator,( T t ) {
CHead<T,1> h = {t};
return h;
}
} head;
int main()
{
assert( (head, 1,2,3,4).contains(1) );
return 0;
}
For the sake of completeness, I'll post a solution that uses Boost.MPL. The following works, but I think Kornel's solution is best.
#include <iostream>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/vector_c.hpp>
struct Contains
{
Contains(int value, bool& result) : value(value), result(result)
{
result = false;
}
template< typename T > void operator()(T x)
{
result = result || (x == value);
}
int value;
bool& result;
};
template <class IntList>
bool isoneof(int val)
{
namespace mpl = boost::mpl;
bool result;
mpl::for_each<IntList>(Contains(val, result));
return result;
}
int main()
{
namespace mpl = boost::mpl;
std::cout << isoneof< mpl::vector_c<int, 1,2,3,5,7,11> >(4) << "\n";
std::cout << isoneof< mpl::vector_c<int, 1,2,3,5,7,11> >(5) << "\n";
}
As you can see, the compile-time array is passed inline as a template argument to isoneof.
This one?
int ints[] = {2,3,5,7,11};
#define ARRAY_SIZE(Array) (sizeof(Array)/sizeof((Array)[0]))
#define INLIST(x,array) isoneof(x,array,ARRAY_SIZE(array))
ADDITION:
template <typename T>
bool isoneof(const T& x, T *array, int n)
{
for(int i=0; i<n; ++i)
if(x==array[i])
return true;
return false;
}
Using C++11, this would be written like this:
template <typename T>
bool isoneof(T value, std::initializer_list<T> arr)
{
using namespace std;
return any_of(begin(arr), end(arr), [&](const T& x) { return x == value; });
}
Just FYI - I solved my particular problem using vararg templates and initializer lists now that I have access to C++14:
template <typename T, typename U>
bool isoneof(T v, U v1) { return v == v1; }
template <typename T, typename U, typename... Args>
bool isoneof(T v, U v1, Args ... others) { return isoneof(v, v1) || isoneof(v, others...); }
template <typename T, typename U>
bool isoneof(T value, std::initializer_list<U> values)
{
for (const auto & e : values)
if (value == e)
return true;
return false;
}