Is the object a vector? [duplicate] - c++

Is it possible to write a type trait whose value is true for all common STL structures (e.g., vector, set, map, ...)?
To get started, I'd like to write a type trait that is true for a vector and false otherwise. I tried this, but it doesn't compile:
template<class T, typename Enable = void>
struct is_vector {
static bool const value = false;
};
template<class T, class U>
struct is_vector<T, typename boost::enable_if<boost::is_same<T, std::vector<U> > >::type> {
static bool const value = true;
};
The error message is template parameters not used in partial specialization: U.

Look, another SFINAE-based solution for detecting STL-like containers:
template<typename T, typename _ = void>
struct is_container : std::false_type {};
template<typename... Ts>
struct is_container_helper {};
template<typename T>
struct is_container<
T,
std::conditional_t<
false,
is_container_helper<
typename T::value_type,
typename T::size_type,
typename T::allocator_type,
typename T::iterator,
typename T::const_iterator,
decltype(std::declval<T>().size()),
decltype(std::declval<T>().begin()),
decltype(std::declval<T>().end()),
decltype(std::declval<T>().cbegin()),
decltype(std::declval<T>().cend())
>,
void
>
> : public std::true_type {};
Of course, you might change methods and types to be checked.
If you want to detect only STL containers (it means std::vector, std::list, etc) you should do something like this.
UPDATE. As #Deduplicator noted, container might not meet AllocatorAwareContainer requirements (e.g.: std::array<T, N>). That is why check on T::allocator_type is not neccessary. But you may check any/all Container requirements in a similar way.

You would say that it should be simpler than that...
template <typename T, typename _ = void>
struct is_vector {
static const bool value = false;
};
template <typename T>
struct is_vector< T,
typename enable_if<
is_same<T,
std::vector< typename T::value_type,
typename T::allocator_type >
>::value
>::type
>
{
static const bool value = true;
};
... But I am not really sure of whether that is simpler or not.
In C++11 you can use type aliases (I think, untested):
template <typename T>
using is_vector = is_same<T, std::vector< typename T::value_type,
typename T::allocator_type > >;
The problem with your approach is that the type U is non-deducible in the context where it is used.

Actually, after some trial and error I found it's quite simple:
template<class T>
struct is_vector<std::vector<T> > {
static bool const value = true;
};
I'd still like to know how to write a more general is_container. Do I have to list all types by hand?

While the other answers here that try to guess whether a class is a container or not might work for you, I would like to present you with the alternative of naming the type you want to return true for. You can use this to build arbitrary is_(something) traits types.
template<class T> struct is_container : public std::false_type {};
template<class T, class Alloc>
struct is_container<std::vector<T, Alloc>> : public std::true_type {};
template<class K, class T, class Comp, class Alloc>
struct is_container<std::map<K, T, Comp, Alloc>> : public std::true_type {};
And so on.
You will need to include <type_traits> and whatever classes you add to your rules.

Why not do something like this for is_container?
template <typename Container>
struct is_container : std::false_type { };
template <typename... Ts> struct is_container<std::list<Ts...> > : std::true_type { };
template <typename... Ts> struct is_container<std::vector<Ts...> > : std::true_type { };
// ...
That way users can add their own containers by partially-specializing. As for is_vector et-al, just use partial specialization as I did above, but limit it to only one container type, not many.

The way I like to detect whether something is a container is to look for data() and size() member functions. Like this:
template <typename T, typename = void>
struct is_container : std::false_type {};
template <typename T>
struct is_container<T
, std::void_t<decltype(std::declval<T>().data())
, decltype(std::declval<T>().size())>> : std::true_type {};

template <typename T>
struct is_container {
template <
typename U,
typename I = typename U::const_iterator
>
static int8_t test(U* u);
template <typename U>
static int16_t test(...);
enum { value = sizeof test <typename std::remove_cv<T>::type> (0) == 1 };
};
template<typename T, size_t N>
struct is_container <std::array<T,N>> : std::true_type { };

Fast forward to 2018 and C++17, I was so daring to improve on #Frank answer
// clang++ prog.cc -Wall -Wextra -std=c++17
#include <iostream>
#include <vector>
namespace dbj {
template<class T>
struct is_vector {
using type = T ;
constexpr static bool value = false;
};
template<class T>
struct is_vector<std::vector<T>> {
using type = std::vector<T> ;
constexpr static bool value = true;
};
// and the two "olbigatory" aliases
template< typename T>
inline constexpr bool is_vector_v = is_vector<T>::value ;
template< typename T>
using is_vector_t = typename is_vector<T>::type ;
} // dbj
int main()
{
using namespace dbj;
std::cout << std::boolalpha;
std::cout << is_vector_v<std::vector<int>> << std::endl ;
std::cout << is_vector_v<int> << std::endl ;
} /* Created 2018 by dbj#dbj.org */
The "proof the pudding". There are better ways to do this, but this works for std::vector.

We can also use concepts. I compiled this with GCC 10.1 flag -std=c++20.
#include<concepts>
template<typename T>
concept is_container = requires (T a)
{
a.begin();
// Uncomment both lines for vectors only
// a.data(); // arrays and vectors
// a.reserve(1); // narrowed down to vectors
};

In our project we still didn't manage to migrate to compiler supporting C++11, so for type_traits of container objects I had to wrote a simple boost style helper:
template<typename Cont> struct is_std_container: boost::false_type {};
template<typename T, typename A>
struct is_std_container<std::vector<T,A> >: boost::true_type {};
template<typename T, typename A>
struct is_std_container<std::list<T,A> >: boost::true_type {};
template<typename T, typename A>
struct is_std_container<std::deque<T,A> >: boost::true_type {};
template<typename K, typename C, typename A>
struct is_std_container<std::set<K,C,A> >: boost::true_type {};
template<typename K, typename T, typename C, typename A>
struct is_std_container<std::map<K,T,C,A> >: boost::true_type {};
template<typename Cont> struct is_std_sequence: boost::false_type {};
template<typename T, typename A>
struct is_std_sequence<std::vector<T,A> >: boost::true_type {};
template<typename T, typename A>
struct is_std_sequence<std::list<T,A> >: boost::true_type {};
template<typename T, typename A>
struct is_std_sequence<std::deque<T,A> >: boost::true_type {};

If you also want to make it work for const std::vector, you can use the following:
namespace local {
template<typename T, typename _ = void>
struct isVector: std::false_type {
};
template<typename T>
struct isVector<T,
typename std::enable_if<
std::is_same<typename std::decay<T>::type, std::vector<typename std::decay<T>::type::value_type, typename std::decay<T>::type::allocator_type> >::value>::type> : std::true_type {
};
}
TEST(TypeTraitTest, testIsVector) {
ASSERT_TRUE(local::isVector<std::vector<int>>::value);
ASSERT_TRUE(local::isVector<const std::vector<int>>::value);
ASSERT_FALSE(local::isVector<std::list<int>>::value);
ASSERT_FALSE(local::isVector<int>::value);
std::vector<uint8_t> output;
std::vector<uint8_t> &output2 = output;
EXPECT_TRUE(core::isVector<decltype(output)>::value);
EXPECT_TRUE(core::isVector<decltype(output2)>::value);
}
Without the std::remove_cv call the second ASSERT_TRUE would fail. But of course this depends on your needs. The thing here is that according to the specs, std::is_same checks for const and volatile to also match.

Related

How can I check if the type `T` is `std::pair<?, bool>` in C++?

We can define a function to insert multiple values to a set like this:
template <typename T, typename... U>
bool insert_all(T& to, const U... arguments) {
return (to.insert(arguments).second && ...);
}
So this code can insert 4, 5 and 6 to the set:
std::set set { 1, 2, 3 };
insert_all(set, 4, 5, 6);
Obviously, type T maybe a type without a method accepting int, called insert and returns std::pair<?, bool>. It's necessary to check it by SFINAE:
template <typename T, typename U, typename = void>
struct can_insert : std::false_type {
};
template <typename T, typename U>
struct can_insert<T, U,
std::enable_if_t<std::is_same_v<decltype(std::declval<T>().insert(std::declval<U>())), std::pair<typename T::iterator, bool>>, void>
> : std::true_type {
};
template <typename T, typename U>
inline constexpr auto can_insert_v = can_insert<T, U>::value;
Pay attention to the second one, ...std::pair<typename T::iterator, bool>>..., how to express it like java code ? extends Pair<?, Boolean> gracefully?
It's not much different than the technique you already coded:
#include <tuple>
#include <type_traits>
template<typename T>
struct is_pair_t_and_bool : std::false_type {};
template<typename T>
struct is_pair_t_and_bool<std::pair<T, bool>> : std::true_type {};
static_assert( is_pair_t_and_bool<std::pair<char, bool>>::value );
static_assert( !is_pair_t_and_bool<int>::value );
static_assert( !is_pair_t_and_bool<std::pair<int, int>>::value );
And, in C++20, once you've gone that far you might as well make it a concept:
template<typename T>
concept pair_t_and_bool=is_pair_t_and_bool<T>::value;
template<pair_t_and_bool T>
struct something {};
something<std::pair<int, bool>> this_compiles;
something<std::pair<int, int >> this_doesnt_compile;
With the help of C++20 concepts, you can define can_insert as concept like:
template<class T, class U>
concept can_insert = std::ranges::range<T> &&
requires(T& to, const U argument) {
{ to.insert(argument) } ->
std::same_as<std::pair<std::ranges::iterator_t<T>, bool>>;
};
Then use it to constrain insert_all like
template<typename T, typename... U>
requires (can_insert<T, U> && ...)
bool insert_all(T& to, const U... arguments) {
return (to.insert(arguments).second && ...);
}

Template metaprogram to find similar consecutive typenames

I am new to template meta programming and was trying to create a program that would find if a parameter pack has consecutive same type names. For example <int, int>, <int, char, char> would return true and <int,char> and <int, char, int> would not.
I managed to write this piece of code but it seems to be comparing each value of parameter pack with itself. I am just looking for a way to iterate through the values of parameter pack to compare with it's consecutive element.
template<typename T, typename U>
struct sameTypename{
enum {value = false};
};
template<typename T>
struct sameTypename<T, T>{
enum {value = true};
};
template <typename T, typename ...args>
struct consTypename{
enum {value = (sameTypename<consTypename<args...>, consTypename<args...>>::value)};
};
template <typename T>
struct consTypename<T, T>{
enum {value = true};
};
template <typename T>
struct consTypename<T>{
enum {value = false};
};
Here you go:
#include <type_traits>
template <typename ...P> struct has_adjacent_same_types : std::false_type {};
template <typename A, typename B, typename ...P> struct has_adjacent_same_types<A, B, P...>
: std::bool_constant<std::is_same_v<A,B> || has_adjacent_same_types<B, P...>::value> {};
I used : std::false_type {}; and : std::bool_constant<X> {}; instead of
{enum{value = false};}; and {enum{value = X};}; respectively, but that's simply a matter of preference.
Some of the features I used are from C++17. If you're using an older version, note that:
std::bool_constant and std::is_same_v are available only starting from C++17 (but that you can use std::integral_constant and std::is_same<>::value before).
(c) #max66
A variation of the HolyBlackCat's solution.
template <typename ...>
struct has_adjacent_same_types : public std::false_type
{ };
template <typename T0, typename ... Ts>
struct has_adjacent_same_types<T0, T0, Ts...> : public std::true_type
{ };
template <typename T0, typename T1, typename ... Ts>
struct has_adjacent_same_types<T0, T1, Ts...>
: public has_adjacent_same_types<T1, Ts...>
{ };
Two simpler specializations instead of only one, more complex.
Substantially is the same things (I suppose) but I find it a little clear to read and understand.
I propose also a completely different solution that uses template folding (so only C++17 or newer, unfortunately) instead of template recursion.
template <typename...>
struct sae_helper;
template <typename ... Ts, typename ... Us>
struct sae_helper<std::tuple<Ts...>, std::tuple<Us...>>
: public std::bool_constant<(std::is_same_v<Ts, Us> || ...)>
{ };
template <typename ... Ts>
struct some_adjacent_equal
: public sae_helper<std::tuple<void, Ts...>, std::tuple<Ts..., void>>
{ };
If void is a possible type in the list of type to check, calling sae_helper from some_adjacent_equal instead of void must be used a different type, obviously.
I suppose that this solution is preferable, over a recursive one, when the list of types is very long because avoid compilers template-recursion limits.
If you can use C++14, you can use a constexpr function instead of template folding (and a tag-type instead of void) as follows
template <typename ... Ts, typename ... Us>
constexpr bool sae_helper (std::tuple<Ts...> const &,
std::tuple<Us...> const &)
{
using unused = bool[];
bool ret { false };
(void)unused { true, ret |= std::is_same<Ts, Us>::value... };
return ret;
}
struct no_type
{ };
template <typename ... Ts>
struct some_adjacent_equal
: public std::integral_constant<bool, sae_helper(std::tuple<no_type, Ts...>{},
std::tuple<Ts..., no_type>{})>
{ };
but, this way, you loose short-circuiting in or evaluation.

Define a struct which is derived from true_type whenever a given SFINAE-able constructor would be taken

Please consider the following code snippet:
template<typename T, class Tuple>
class vector
{
using size_type = typename Tuple::size_type;
template<typename... Elements,
typename = decltype(std::declval<Tuple>().reserve(size_type()))>
typename = decltype(std::declval<Tuple>().push_back(T())),
vector(Elements&&... elements)
{ /* ... */ }
};
I want to define a nested struct supports_reserve_push_back which is derived from std::true_type whenever the constructor above would be enabled (and which is derived from std::false_type in the other case).
How can I do this?
I've modified the code to make it build. And implemented the trait you requested, to the best of my understanding.
#include <iostream>
#include <type_traits>
#include <vector>
#include <map>
namespace example {
template<typename...>
using void_t = void;
template<typename T, class Tuple>
struct vector {
using size_type = typename Tuple::size_type;
using tuple_type = Tuple;
using elem_type = T;
template<typename... Elements>
vector(Elements&&... elements)
{ /* ... */ }
};
template <class T, typename = void>
struct supports_reserve_push_back : std::false_type {};
template <class Vec>
struct supports_reserve_push_back<Vec, void_t<
decltype(std::declval<typename Vec::tuple_type>().reserve(typename Vec::size_type())),
decltype(std::declval<typename Vec::tuple_type>().push_back(typename Vec::elem_type())) >
>
: std::true_type {};
}
int main() {
std::cout
<< example::supports_reserve_push_back<example::vector<int, std::vector<int>>>::value
<< '\n'
<< example::supports_reserve_push_back<example::vector<int, std::map<int, int>>>::value;
return 0;
}
A few thing to note:
The way you wrote the c'tor originally caused a hard error when instantiating the class in the negative case. That's why I removed the chcck from the c'tor.
I'd suggest you define the type traits first, and use them to enable your c'tors.
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=details::can_apply<Z,void,Ts...>;
Wrap up your decltypes into template usings and do some && and done.
There is also a std experimental similar to above.
template<class T, class U>
using push_back_r = decltype(std::declval<T>().push_back(std::declval<U>()));
template<class T>
using reserve_r = decltype(std::declval<T>().reserve(1));
template<class T, class U>
constexpr can_apply<push_back_r,T,U> has_push_back={};
template<class T>
constexpr can_apply<reserve_r,T> has_reserve={};
template<bool b>using bool_t=std::integral_constant<bool,b>;
template<class T,class U>
constexpr bool_t<has_push_back<T,U>&&has_reserve<T>>
efficiently_fillable_with = {};
Then efficiently_fillable_with<T,U> is true type iff you can reserve space with T and then push Us into it. The r/l value category of T and U is preserved: if you want to know about filling an non-cinstant lvalue of T with rvalue Us:
efficiently_fillable_with<T&,U>
If you want to fill with U const& instead of rvalues, pass U const&.
#include <type_traits>
#include <utility>
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_t<>, Operation, Args...>;
template <typename T, typename Sz>
using has_reserve = decltype(std::declval<T>().reserve(std::declval<Sz>()));
template <typename T, typename U>
using has_push_back = decltype(std::declval<T>().push_back(std::declval<U>()));
template <typename Tuple, typename T, typename size_type>
constexpr bool supports_reserve_push_back = detect<has_reserve, Tuple, size_type>{} && detect<has_push_back, Tuple, T>{};
Test:
template <typename T, class Tuple>
class vector
{
public:
using size_type = typename Tuple::size_type;
template <typename... Elements, typename U = Tuple,
std::enable_if_t<supports_reserve_push_back<U&, T, size_type>, int> = 0>
vector(Elements&&... elements)
{
}
template <typename... Elements, typename U = Tuple,
std::enable_if_t<!supports_reserve_push_back<U&, T, size_type>, int> = 0>
vector(Elements&&... elements)
{
}
};
DEMO
I would try the following approach:
Have your vector template class inherit from a superclass, like this:
template<typename T, class Tuple> class vector
: public supports_reserve_push_back_impl<
vector_has_default_constructor<T, Tuple>::value() > {
// ...
}
Now, define a vector_has_default_constructor template class that takes the same template parameters:
template<typename T, class Tuple> class vector_has_default_constructor {
public:
// ...
};
In vector_has_default_constructor:
Define a constexpr bool value() method with the same exact signature as the vector's constructor. This constexpr method returns true.
Define an overload constexpr bool value() with a ... signature, which should have lower priority in the overload resolution. This constexpr returns false.
Now, this situation is reduced to defining two trivial specializations, supports_reserve_push_back_impl<true> and supports_reserve_push_back_impl<false>.
supports_reserve_push_back_impl<true> contains your desired supports_reserve_push_back value, and is inherited by your vector.
supports_reserve_push_back_impl<false> is empty.

Find out whether a C++ object is callable

Is it possible to write a type trait, say is_callable<T> which tells if an object has an operator() defined?
It is easy if the arguments to the call operator are known in advance, but not in the general case.
I want the trait to return true if and only if there is at least one overloaded call operator defined.
This question is related and has a good answer, but it doesn't work on all types (only on int-convertible types). Also, std::is_function works, but only on proper C++ functions, not on functors. I'm looking for a more general solution.
I think this trait does what you want. It detects operator() with any kind of signature even if it's overloaded and also if it's templatized:
template<typename T>
struct is_callable {
private:
typedef char(&yes)[1];
typedef char(&no)[2];
struct Fallback { void operator()(); };
struct Derived : T, Fallback { };
template<typename U, U> struct Check;
template<typename>
static yes test(...);
template<typename C>
static no test(Check<void (Fallback::*)(), &C::operator()>*);
public:
static const bool value = sizeof(test<Derived>(0)) == sizeof(yes);
};
The principle is based on Member Detector idiom. As it is, it will fail to compile if you pass it a non-class type, but that shouldn't be hard to fix, I just left it out for brevity. You can also extend it to report true for functions.
Of course it doesn't give you any info about the signature(s) of operator() whatsoever, but I believe that's not what you asked for, right?
EDIT for Klaim:
It's simple enough to make it work (return false) with non-class types. If you rename the above class to is_callable_impl, you can write this, for example:
template<typename T>
struct is_callable
: std::conditional<
std::is_class<T>::value,
is_callable_impl<T>,
std::false_type
>::type
{ };
The answers here were helpful but I came here wanting something that could also spot whether something was callable regardless of whether it happened to be an object or a classic function. jrok's answer to this aspect of the problem, alas, didn't work because std::conditional actually evaluates the types of both arms!
So, here's a solution:
// Note that std::is_function says that pointers to functions
// and references to functions aren't functions, so we'll make our
// own is_function_t that pulls off any pointer/reference first.
template<typename T>
using remove_ref_t = typename std::remove_reference<T>::type;
template<typename T>
using remove_refptr_t = typename std::remove_pointer<remove_ref_t<T>>::type;
template<typename T>
using is_function_t = typename std::is_function<remove_refptr_t<T>>::type;
// We can't use std::conditional because it (apparently) must determine
// the types of both arms of the condition, so we do it directly.
// Non-objects are callable only if they are functions.
template<bool isObject, typename T>
struct is_callable_impl : public is_function_t<T> {};
// Objects are callable if they have an operator(). We use a method check
// to find out.
template<typename T>
struct is_callable_impl<true, T> {
private:
struct Fallback { void operator()(); };
struct Derived : T, Fallback { };
template<typename U, U> struct Check;
template<typename>
static std::true_type test(...);
template<typename C>
static std::false_type test(Check<void (Fallback::*)(), &C::operator()>*);
public:
typedef decltype(test<Derived>(nullptr)) type;
};
// Now we have our final version of is_callable_t. Again, we have to take
// care with references because std::is_class says "No" if we give it a
// reference to a class.
template<typename T>
using is_callable_t =
typename is_callable_impl<std::is_class<remove_ref_t<T>>::value,
remove_ref_t<T> >::type;
But in the end, for my application, I really wanted to just know whether you could say f() (i.e., call it with no arguments), so I instead went with something much simpler.
template <typename T>
constexpr bool noarg_callable_impl(
typename std::enable_if<bool(sizeof((std::declval<T>()(),0)))>::type*)
{
return true;
}
template<typename T>
constexpr bool noarg_callable_impl(...)
{
return false;
}
template<typename T>
constexpr bool is_noarg_callable()
{
return noarg_callable_impl<T>(nullptr);
}
In fact, I went even further. I knew the function was supposed to return an int, so rather than just check that I could call it, I checked the return type, too, by changing the enable_if to:
typename std::enable_if<std::is_convertible<decltype(std::declval<T>()()),
int>::value>::type*)
Hope this helps someone!
Here is a possible solution using C++11 that works without requiring to know the signature of the call operator for functors, but only as long the functor does not have more than one overload of operator ():
#include <type_traits>
template<typename T, typename = void>
struct is_callable : std::is_function<T> { };
template<typename T>
struct is_callable<T, typename std::enable_if<
std::is_same<decltype(void(&T::operator())), void>::value
>::type> : std::true_type { };
This is how you would use it:
struct C
{
void operator () () { }
};
struct NC { };
struct D
{
void operator () () { }
void operator () (int) { }
};
int main()
{
static_assert(is_callable<C>::value, "Error");
static_assert(is_callable<void()>::value, "Error");
auto l = [] () { };
static_assert(is_callable<decltype(l)>::value, "Error");
// Fires! (no operator())
static_assert(is_callable<NC>::value, "Error");
// Fires! (several overloads of operator ())
static_assert(is_callable<D>::value, "Error");
}
C++17 brings std::is_invocable and friends.
This answer also given a solution on how to emulate it with C++14.
There are several other answers already, of course, and they are useful, but none of them seem to cover every use case AFAICT. Borrowing from those answers and this possible implementation of std::is_function, I created a version that covers every possible use case of which I could think. It's kind of lengthy, but very feature complete (Demo).
template<typename T, typename U = void>
struct is_callable
{
static bool const constexpr value = std::conditional_t<
std::is_class<std::remove_reference_t<T>>::value,
is_callable<std::remove_reference_t<T>, int>, std::false_type>::value;
};
template<typename T, typename U, typename ...Args>
struct is_callable<T(Args...), U> : std::true_type {};
template<typename T, typename U, typename ...Args>
struct is_callable<T(*)(Args...), U> : std::true_type {};
template<typename T, typename U, typename ...Args>
struct is_callable<T(&)(Args...), U> : std::true_type {};
template<typename T, typename U, typename ...Args>
struct is_callable<T(Args......), U> : std::true_type {};
template<typename T, typename U, typename ...Args>
struct is_callable<T(*)(Args......), U> : std::true_type {};
template<typename T, typename U, typename ...Args>
struct is_callable<T(&)(Args......), U> : std::true_type {};
template<typename T, typename U, typename ...Args>
struct is_callable<T(Args...)const, U> : std::true_type {};
template<typename T, typename U, typename ...Args>
struct is_callable<T(Args...)volatile, U> : std::true_type {};
template<typename T, typename U, typename ...Args>
struct is_callable<T(Args...)const volatile, U> : std::true_type {};
template<typename T, typename U, typename ...Args>
struct is_callable<T(Args......)const, U> : std::true_type {};
template<typename T, typename U, typename ...Args>
struct is_callable<T(Args......)volatile, U> : std::true_type{};
template<typename T, typename U, typename ...Args>
struct is_callable<T(Args......)const volatile, U> : std::true_type {};
template<typename T, typename U, typename ...Args>
struct is_callable<T(Args...)&, U> : std::true_type {};
template<typename T, typename U, typename ...Args>
struct is_callable<T(Args...)const&, U> : std::true_type{};
template<typename T, typename U, typename ...Args>
struct is_callable<T(Args...)volatile&, U> : std::true_type{};
template<typename T, typename U, typename ...Args>
struct is_callable<T(Args...)const volatile&, U> : std::true_type{};
template<typename T, typename U, typename ...Args>
struct is_callable<T(Args......)&, U> : std::true_type {};
template<typename T, typename U, typename ...Args>
struct is_callable<T(Args......)const&, U> : std::true_type{};
template<typename T, typename U, typename ...Args>
struct is_callable<T(Args......)volatile&, U> : std::true_type{};
template<typename T, typename U, typename ...Args>
struct is_callable<T(Args......)const volatile&, U> : std::true_type{};
template<typename T, typename U, typename ...Args>
struct is_callable<T(Args...)&&, U> : std::true_type{};
template<typename T, typename U, typename ...Args>
struct is_callable<T(Args...)const&&, U> : std::true_type{};
template<typename T, typename U, typename ...Args>
struct is_callable<T(Args...)volatile&&, U> : std::true_type{};
template<typename T, typename U, typename ...Args>
struct is_callable<T(Args...)const volatile&&, U> : std::true_type{};
template<typename T, typename U, typename ...Args>
struct is_callable<T(Args......)&&, U> : std::true_type{};
template<typename T, typename U, typename ...Args>
struct is_callable<T(Args......)const&&, U> : std::true_type{};
template<typename T, typename U, typename ...Args>
struct is_callable<T(Args......)volatile&&, U> : std::true_type{};
template<typename T, typename U, typename ...Args>
struct is_callable<T(Args......)const volatile&&, U> : std::true_type{};
template<typename T>
struct is_callable<T, int>
{
private:
using YesType = char(&)[1];
using NoType = char(&)[2];
struct Fallback { void operator()(); };
struct Derived : T, Fallback {};
template<typename U, U>
struct Check;
template<typename>
static YesType Test(...);
template<typename C>
static NoType Test(Check<void (Fallback::*)(), &C::operator()>*);
public:
static bool const constexpr value = sizeof(Test<Derived>(0)) == sizeof(YesType);
};
This works correctly with non-class types (returns false, of course), function types (<T()>), function pointer types, function reference types, functor class types, bind expressions, lambda types, etc. This works correctly even if the class constructor is private and/or non-defaulted, and even if operator() is overloaded. This returns false for member function pointers by design because they are not callable, but you can use bind to create a callable expression.
Note: These assume that the default constructor is valid for the type your checking. Not sure offhand how to get around that.
The following seems to work if it's callable with 0 arguments. Is there something in is_function's implementation that might help to extend this to 1 or more argument callables?:
template <typename T>
struct is_callable {
// Types "yes" and "no" are guaranteed to have different sizes,
// specifically sizeof(yes) == 1 and sizeof(no) == 2.
typedef char yes[1];
typedef char no[2];
template <typename C>
static yes& test(decltype(C()())*);
template <typename>
static no& test(...);
// If the "sizeof" the result of calling test<T>(0) would be equal to the sizeof(yes),
// the first overload worked and T has a nested type named foobar.
static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};
If you know the type of the argument (even if it's a template parameter), the following would work for 1 argument, and I imagine one could extend pretty easily from there:
template <typename T, typename T2>
struct is_callable_1 {
// Types "yes" and "no" are guaranteed to have different sizes,
// specifically sizeof(yes) == 1 and sizeof(no) == 2.
typedef char yes[1];
typedef char no[2];
template <typename C>
static yes& test(decltype(C()(T2()))*);
template <typename, typename>
static no& test(...);
// If the "sizeof" the result of calling test<T>(0) would be equal to the sizeof(yes),
// the first overload worked and T has a nested type named foobar.
static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};
Edit
here is a modification that handles the case where default constructor isn't available.
This is a neat and short trick for finding if T is callable. It goes along the lines originally proposed by Walter E. Brown at CPPCON'14 in his talk on modern template metaprogramming.
template <class... >
using void_t = void;
template <class T>
using has_opr_t = decltype(&T::operator());
template <class T, class = void>
struct is_callable : std::false_type { };
template <class T>
struct is_callable<T, void_t<has_opr_t<typename std::decay<T>::type>>> : std::true_type { };
Here is another implementation.
It makes use of std::is_function template for free functions.
For classes, it uses something similar to the Member Detector Idiom. If T has a call operator, callable_2 will contain more than one operator(). This will cause the first can_call function to be discarded (through SFINAE) due to ambiguity failure in decltype(&callable_2<T>::operator()) and the second can_call function will return true. If T does not have a call operator, the first can_call function will be used (due to overload resolution rules).
namespace impl
{
struct callable_1 { void operator()(); };
template<typename T> struct callable_2 : T, callable_1 { };
template<typename T>
static constexpr bool can_call(decltype(&callable_2<T>::operator())*) noexcept { return false; }
template<typename>
static constexpr bool can_call(...) noexcept { return true; }
template<bool is_class, typename T>
struct is_callable : public std::is_function<T> { };
template<typename T> struct is_callable<false, T*> : public is_callable<false, T> { };
template<typename T> struct is_callable<false, T* const> : public is_callable<false, T> { };
template<typename T> struct is_callable<false, T* volatile> : public is_callable<false, T> { };
template<typename T> struct is_callable<false, T* const volatile> : public is_callable<false, T> { };
template<typename T>
struct is_callable<true, T> : public std::integral_constant<bool, can_call<T>(0)> { };
}
template<typename T>
using is_callable = impl::is_callable<std::is_class<std::remove_reference_t<T>>::value,
std::remove_reference_t<T>>;

Select every even (or odd) argument in template parameter pack

I would like to allow use of the class I'm writing to specify as a template parameters a list of types along with a list of allocators of those types in a manner that types are at odd positions and allocators are at even ones:
template<typename... T>
class MyClass {
// Stuff inside
}
int main() {
MyClass<SomeType1, AllocatorOfSomeType1> c1;
MyClass<SomeType1, AllocatorOfSomeType1,
SomeType2, AllocatorOfSomeType2> c2;
MyClass<SomeType1, AllocatorOfSomeType1,
SomeType2, AllocatorOfSomeType2,
SomeType3, AllocatorOfSomeType3> c3;
// And so on....
}
Internally it would make sense to have a tuple of vectors of types for storage:
std::tuple<std::vector<EveryOddTypeInParameterPack>...> m_storage_;
and a tuple of allocators for usage:
std::tuple<std::vector<EveryEvenTypeInParameterPack>...> m_storage_;
How can I actually declare those tuples in code? In theory I need to somehow select every odd/even type in parameter pack - is that possible?
Though the code got a little lengthy, I suppose the mechanism doesn't have
unnecessary peculiarities.
If I understand the question correctly,
probably the following code will meet the purpose:
// push front for tuple
template< class, class > struct PFT;
template< class A, class... T > struct PFT< A, tuple< T... > > {
typedef tuple< A, T... > type;
};
// for even
template< class... > struct even_tuple;
template< class A, class B > struct even_tuple< A, B > {
typedef tuple< A > type;
};
template< class A, class B, class... T > struct even_tuple< A, B, T... > {
typedef typename PFT< A, typename even_tuple< T... >::type >::type type;
};
// As for odd elements, in the same way as even(please see the test on ideone)
// objective type
template< class > struct storage_type;
template< class... T > struct storage_type< tuple< T... > > {
typedef tuple< vector< T >... > type;
};
template< class... T >
struct MyClass {
typename storage_type< typename even_tuple< T... >::type >::type
m_storage_even_;
typename storage_type< typename odd_tuple< T... >::type >::type
m_storage_odd_;
};
Here is a test on ideone.
Perhaps something like this:
#include <tuple>
// Example receptacle
template <typename ...Args> struct MyContainer;
// Tuple concatenator
template<typename PackR, typename PackL> struct cat;
template<typename ...R, typename ...L>
struct cat<std::tuple<R...>, std::tuple<L...>>
{
typedef std::tuple<R..., L...> type;
};
// Even/Odd extractors
template <typename ...Args> struct GetEven;
template <typename ...Args> struct GetOdd;
template <typename E1, typename O1, typename ...Args>
struct GetEven<E1, O1, Args...>
{
typedef typename cat<std::tuple<E1>, typename GetEven<Args...>::value>::type value;
};
template <typename E1, typename O1>
struct GetEven<E1, O1>
{
typedef std::tuple<E1> value;
};
template <typename E1, typename O1, typename ...Args>
struct GetOdd<E1, O1, Args...>
{
typedef typename cat<std::tuple<O1>, typename GetEven<Args...>::value>::type value;
};
template <typename E1, typename O1>
struct GetOdd<E1, O1>
{
typedef std::tuple<O1> value;
};
// Tuple-to-Receptacle mover
template <typename Pack, template <typename ...T> class Receiver> struct Unpack;
template <typename ...Args, template <typename ...T> class Receiver>
struct Unpack<std::tuple<Args...>, Receiver>
{
typedef Receiver<Args...> type;
};
// Example consumer
template <typename ...Args>
struct Foo
{
typedef typename Unpack<typename GetEven<Args...>::value, MyContainer>::type EvenVector;
typedef typename Unpack<typename GetOdd<Args...>::value, MyContainer>::type OddVector;
EvenVector x;
OddVector y;
};
You still have to define your MyContainer class to do something useful with the variadic parameters, e.g. implement your tuple of vectors... (why not a vector of tuples, though?)
Credits to brunocodutra for the tuple trick.
this is just a try
template<typename... T> class Myclass;
template<typename T1, typename allocT1>
class MyClass <T1, allocT1> {
std::pair<T1, allocT1> myFirstArglist;
//and you have to do a check that allocT1::value_type is same as T1 or not
//or may be alloT1 is an allocator type or not(i'm thinking concepts, may be)
//this idea is inspired from Chris's comment
};
template<typename T1, typename allocT1, typename... T>
class Myclass<T1, allocT1, T...> {
std::pair<T1, allocT1> myFirstArglist;
Myclass<T>; //something like this
};
template<>
class Myclass<> {
//probably you would like some error message here
//when there are no types and containers
};
may be i'm not clear enough, you'd probably like to read
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2080.pdf
Also there is a good post related to design of allocator types... you would like to have a look at:
C++ Design Pattern for allocator type arguments
I know your question was originally tagged "c++11", but I figure it's worth pointing out for posterity that in C++14 you have access to make_index_sequence, and that makes the whole thing pretty simple. For filtering a tuple, I'd start with this outline: https://quuxplusone.github.io/blog/2018/07/23/metafilter/
And then we end up with something like this (Godbolt):
template<bool> struct zero_or_one {
template<class E> using type = std::tuple<E>;
};
template<> struct zero_or_one<false> {
template<class E> using type = std::tuple<>;
};
template<class Tuple, class = std::make_index_sequence<std::tuple_size<Tuple>::value>>
struct just_evens;
template<class... Es, size_t... Is>
struct just_evens<std::tuple<Es...>, std::index_sequence<Is...>> {
using type = decltype(std::tuple_cat(
std::declval<typename zero_or_one<Is % 2 == 0>::template type<Es>>()...
));
};
To get just_odds, you'd switch the condition from Is % 2 == 0 to Is % 2 != 0.
Example usage:
static_assert(std::is_same<
just_evens<std::tuple<char, short, int, long, double>>::type,
std::tuple<char, int, double>
>::value, "");