I have a template:
template<typename... Ts> //T1,T2,T3,...
struct foo {
//my struct
};
I want to do static_assert checks on T1,T3,T5,... (the "odd types") and on T2,T4,T6,... (the "even types") separately.
I have found this simple solution:
template<size_t N, typename... Ts>
struct perform_checks {};
template<size_t N, typename T, typename U, typename... Ts>
struct perform_checks<N, T, U, Ts...> : perform_checks<N, Ts...>
{
//check for odd types
static_assert(std::is_default_constructible<T>::value,"failure");
//check for even types
static_assert(std::is_copy_constructible<U>::value,"failure");
};
The N parameter allows it to end. I use it like this:
template<typename... Ts>
struct foo {
perform_checks<0,Ts...> hello;
};
This seems to be working fine. But is it possible to avoid the hello variable? I never use it for any other purpose.
Derive foo from perform_checks<> privately:
template <typename... Ts> struct foo : private perform_checks<Ts...> {
// stuff
};
Oh, and get rid of the N parameter that you don't need:
template <typename... Ts> struct perform_checks {};
template <typename T> struct perform_checks<T> {
template <typename U> struct dependent_name_hack : std::false_type {};
static_assert(dependent_name_hack<T>::value,
"Odd number of parameters not acceptable.");
};
template <typename T, typename U, typename... Ts>
struct perform_checks<T, U, Ts...> : perform_checks<Ts...> {
//check for odd types
static_assert(std::is_default_constructible<T>::value,"failure");
//check for even types
static_assert(std::is_copy_constructible<U>::value,"failure");
};
You can use enable_if1 (and boost::mpl) in more-or-less the following way:
#include <boost/mpl/and.hpp>
template<size_t N, typename... Ts>
struct perform_checks {};
template<size_t N, typename T, typename U, typename... Ts>
struct perform_checks<N, T, U, Ts...> : perform_checks<N, Ts...>
{
typedef boost::mpl::and_<std::is_default_constructible<T>::type,
std::is_copy_constructible<U>::type> type;
};
template < class... Ts,
class = typename std::enable_if<perform_checks<0, Ts...>::type>
struct foo {
//my struct
};
The only purpose of foo in the OP is triggering the check when it's instantiated. That's why you need the variable hello: it's an instantiation of foo.
I would rather follow the approach of traits in <type_traits>. More precisely, I would turn perform_checks into class (or struct) that has public static constexpt bool member called value which is true or false depending on whether the given types pass the test or not. Then I would use a single static_assert to stop compilation if value is false.
My solution, which assumes that the number of template type arguments is even, follows:
#include <type_traits>
template<typename First, typename Second, typename... Others>
struct perform_checks :
std::integral_constant<bool,
perform_checks<First, Second>::value && // Checks First and Second
perform_checks<Others...>::value // Recursively "calls" itself on Others
> {
};
// This specialization finishes the recursion and effectively performs the test
template<typename First, typename Second>
struct perform_checks<First, Second> :
std::integral_constant<bool,
std::is_default_constructible<First>::value && // Checks First
std::is_copy_constructible<Second>::value // Checks Second
> {
};
Here is a simple test:
struct NonDefaultConstructible {
NonDefaultConstructible() = delete;
};
struct NonCopyConstructible {
NonCopyConstructible(const NonCopyConstructible&) = delete;
};
int main() {
static_assert(perform_checks<int, double>::value, "Failure");
static_assert(perform_checks<int, int, double, double>::value, "Failure");
static_assert(!perform_checks<NonDefaultConstructible, int>::value, "Failure");
static_assert(!perform_checks<int, NonCopyConstructible>::value, "Failure");
static_assert(!perform_checks<int, int, double, NonCopyConstructible>::value, "Failure");
}
Notice that no variable was created.
Related
Is there a utility in the standard library to get the index of a given type in std::variant? Or should I make one for myself? That is, I want to get the index of B in std::variant<A, B, C> and have that return 1.
There is std::variant_alternative for the opposite operation. Of course, there could be many same types on std::variant's list, so this operation is not a bijection, but it isn't a problem for me (I can have first occurrence of type on list, or unique types on std::variant list).
Update a few years later: My answer here may be a cool answer, but this is the correct one. That is how I would solve this problem today.
We could take advantage of the fact that index() almost already does the right thing.
We can't arbitrarily create instances of various types - we wouldn't know how to do it, and arbitrary types might not be literal types. But we can create instances of specific types that we know about:
template <typename> struct tag { }; // <== this one IS literal
template <typename T, typename V>
struct get_index;
template <typename T, typename... Ts>
struct get_index<T, std::variant<Ts...>>
: std::integral_constant<size_t, std::variant<tag<Ts>...>(tag<T>()).index()>
{ };
That is, to find the index of B in variant<A, B, C> we construct a variant<tag<A>, tag<B>, tag<C>> with a tag<B> and find its index.
This only works with distinct types.
I found this answer for tuple and slightly modificated it:
template<typename VariantType, typename T, std::size_t index = 0>
constexpr std::size_t variant_index() {
static_assert(std::variant_size_v<VariantType> > index, "Type not found in variant");
if constexpr (index == std::variant_size_v<VariantType>) {
return index;
} else if constexpr (std::is_same_v<std::variant_alternative_t<index, VariantType>, T>) {
return index;
} else {
return variant_index<VariantType, T, index + 1>();
}
}
It works for me, but now I'm curious how to do it in old way without constexpr if, as a structure.
You can also do this with a fold expression:
template <typename T, typename... Ts>
constexpr size_t get_index(std::variant<Ts...> const&) {
size_t r = 0;
auto test = [&](bool b){
if (!b) ++r;
return b;
};
(test(std::is_same_v<T,Ts>) || ...);
return r;
}
The fold expression stops the first time we match a type, at which point we stop incrementing r. This works even with duplicate types. If a type is not found, the size is returned. This could be easily changed to not return in this case if that's preferable, since missing return in a constexpr function is ill-formed.
If you dont want to take an instance of variant, the argument here could instead be a tag<variant<Ts...>>.
With Boost.Mp11 this is a short, one-liner:
template<typename Variant, typename T>
constexpr size_t IndexInVariant = mp_find<Variant, T>::value;
Full example:
#include <variant>
#include <boost/mp11/algorithm.hpp>
using namespace boost::mp11;
template<typename Variant, typename T>
constexpr size_t IndexInVariant = mp_find<Variant, T>::value;
int main()
{
using V = std::variant<int,double, char, double>;
static_assert(IndexInVariant<V, int> == 0);
// for duplicates first idx is returned
static_assert(IndexInVariant<V, double> == 1);
static_assert(IndexInVariant<V, char> == 2);
// not found returns ".end()"/ or size of variant
static_assert(IndexInVariant<V, float> == 4);
// beware that const and volatile and ref are not stripped
static_assert(IndexInVariant<V, int&> == 4);
static_assert(IndexInVariant<V, const int> == 4);
static_assert(IndexInVariant<V, volatile int> == 4);
}
One fun way to do this is to take your variant<Ts...> and turn it into a custom class hierarchy that all implement a particular static member function with a different result that you can query.
In other words, given variant<A, B, C>, create a hierarchy that looks like:
struct base_A {
static integral_constant<int, 0> get(tag<A>);
};
struct base_B {
static integral_constant<int, 1> get(tag<B>);
};
struct base_C {
static integral_constant<int, 2> get(tag<C>);
};
struct getter : base_A, base_B, base_C {
using base_A::get, base_B::get, base_C::get;
};
And then, decltype(getter::get(tag<T>())) is the index (or doesn't compile). Hopefully that makes sense.
In real code, the above becomes:
template <typename T> struct tag { };
template <std::size_t I, typename T>
struct base {
static std::integral_constant<size_t, I> get(tag<T>);
};
template <typename S, typename... Ts>
struct getter_impl;
template <std::size_t... Is, typename... Ts>
struct getter_impl<std::index_sequence<Is...>, Ts...>
: base<Is, Ts>...
{
using base<Is, Ts>::get...;
};
template <typename... Ts>
struct getter : getter_impl<std::index_sequence_for<Ts...>, Ts...>
{ };
And once you establish a getter, actually using it is much more straightforward:
template <typename T, typename V>
struct get_index;
template <typename T, typename... Ts>
struct get_index<T, std::variant<Ts...>>
: decltype(getter<Ts...>::get(tag<T>()))
{ };
That only works in the case where the types are distinct. If you need it to work with independent types, then the best you can do is probably a linear search?
template <typename T, typename>
struct get_index;
template <size_t I, typename... Ts>
struct get_index_impl
{ };
template <size_t I, typename T, typename... Ts>
struct get_index_impl<I, T, T, Ts...>
: std::integral_constant<size_t, I>
{ };
template <size_t I, typename T, typename U, typename... Ts>
struct get_index_impl<I, T, U, Ts...>
: get_index_impl<I+1, T, Ts...>
{ };
template <typename T, typename... Ts>
struct get_index<T, std::variant<Ts...>>
: get_index_impl<0, T, Ts...>
{ };
My two cents solutions:
template <typename T, typename... Ts>
constexpr std::size_t variant_index_impl(std::variant<Ts...>**)
{
std::size_t i = 0; ((!std::is_same_v<T, Ts> && ++i) && ...); return i;
}
template <typename T, typename V>
constexpr std::size_t variant_index_v = variant_index_impl<T>(static_cast<V**>(nullptr));
template <typename T, typename V, std::size_t... Is>
constexpr std::size_t variant_index_impl(std::index_sequence<Is...>)
{
return ((std::is_same_v<T, std::variant_alternative_t<Is, V>> * Is) + ...);
}
template <typename T, typename V>
constexpr std::size_t variant_index_v = variant_index_impl<T, V>(std::make_index_sequence<std::variant_size_v<V>>{});
If you wish a hard error on lookups of not containing type or duplicate type - here are static asserts:
constexpr auto occurrences = (std::is_same_v<T, Ts> + ...);
static_assert(occurrences != 0, "The variant cannot have the type");
static_assert(occurrences <= 1, "The variant has duplicates of the type");
Another take on it:
#include <type_traits>
namespace detail {
struct count_index {
std::size_t value = 0;
bool found = false;
template <typename T, typename U>
constexpr count_index operator+(const std::is_same<T, U> &rhs)
{
if (found)
return *this;
return { value + !rhs, rhs};
}
};
}
template <typename Seq, typename T>
struct index_of;
template <template <typename...> typename Seq, typename... Ts, typename T>
struct index_of<Seq<Ts...>, T>: std::integral_constant<std::size_t, (detail::count_index{} + ... + std::is_same<T, Ts>{}).value> {
static_assert(index_of::value < sizeof...(Ts), "Sequence doesn't contain the type");
};
And then:
#include <variant>
struct A{};
struct B{};
struct C{};
using V = std::variant<A, B, C>;
static_assert(index_of<V, B>::value == 1);
Or:
static_assert(index_of<std::tuple<int, float, bool>, float>::value == 1);
See on godbolt: https://godbolt.org/z/7ob6veWGr
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.
template <unsigned int N> class myclass
{
public:
template <typename... Args> void mymethod(Args... args)
{
// Do interesting stuff
}
};
I want mymethod to be called only with exactly N doubles. Is that possible? That is, say that I have:
myclass <3> x;
x.mymethod(3., 4., 5.); // This works
x.mymethod('q', 1., 7.); // This doesn't work
x.mymethod(1., 2.); // This doesn't work
How can I get this done?
For the number of arguments constraint you can easily check if sizeof...(Args) == N but for checking if all the arguments are doubles you need to build a recursive type trait that checks std::is_same for each of the arguments.
template<typename...>
struct are_same : std::true_type
{};
template<typename T>
struct are_same<T> : std::true_type
{};
template<typename T, typename U, typename... Types>
struct are_same<T, U, Types...> :
std::integral_constant<bool, (std::is_same<T, U>::value && are_same<T, Types...>::value)>
{};
Notice are_same is first declared and then specialized.
Then just implement the constraint in your method return type using std::enable_if by taking advantage of SFINAE.
template <unsigned int N> class myclass
{
public:
template <typename... Args>
typename std::enable_if<(are_same<double, Args...>::value && sizeof...(Args) == N), void>::type
/* void */ mymethod(Args... args)
{
// Do interesting stuff
}
};
Can try something like following :
#include <type_traits>
template<class T, class...>
struct all_same : std::true_type
{};
template<class T, class U, class... TT>
struct all_same<T, U, TT...>
: std::integral_constant<bool, std::is_same<T,U>{} && all_same<T, TT...>{}>
{};
template <unsigned int N> class myclass
{
public:
template <typename... Args>
typename std::enable_if<sizeof...(Args) == N, void >::type mymethod(Args... args)
{
static_assert(all_same<double, Args...>{},
"Not all args as Double");
}
};
<Demo>
Say I have a get_at metafunction which gets the Nth type from a variadic template parameter list:
template <int I, typename ...Ts>
struct get_at;
template <int I, typename T, typename ...Ts>
struct get_at<I, T, Ts...> : public get_at<I-1, Ts...>
{
};
template <typename T, typename ...Ts>
struct get_at<0, T, Ts...> : public std::true_type
{
typedef T type;
};
template <int I>
struct get_at<I> : public std::false_type
{
};
And I'd like to store the Ts... in a list type like so:
template <typename... Ts>
struct list {};
How would I get the Ts... out of the containing list type so that I can put it into the get_at metafunction?
You don't have to. Just write another metafunction (any problem can be solved by another layer of indirection?):
template <int I, typename Seq>
struct get_at_seq;
template <int I, typename... Ts>
struct get_at_seq<I, list<Ts...>>
: get_at<I, Ts...>
{ };
Or even:
template <int I, template <typename...> class C, typename... Ts>
struct get_at_seq<I, C<Ts...>>
: get_at<I, Ts...>
{ };
A note though, inheriting from true_type or false_type doesn't make sense for this use-case. You override type, but then you still have operator bool() on get_at, which makes no sense for this usage. Better to just write in value explicitly, e.g.:
template <typename T, typename ...Ts>
struct get_at<0, T, Ts...>
{
typedef T type;
static constexpr bool value = true;
};
How can I make a class template that returns whether any of its variadic types are equal to the first type. I want to be able to do this:
is_same<T, A, B, C>::value; // true if T is one of A, B or C
And if T is equal to any one of those types, its static value member will be true, otherwise false. How can I do this?
Nice and concise with C++17:
template <class T, class... Ts>
struct is_any : std::disjunction<std::is_same<T, Ts>...> {};
And the dual:
template <class T, class... Ts>
struct are_same : std::conjunction<std::is_same<T, Ts>...> {};
A variation that uses fold expressions:
template <class T, class... Ts>
struct is_any : std::bool_constant<(std::is_same_v<T, Ts> || ...)> {};
template <class T, class... Ts>
struct are_same : std::bool_constant<(std::is_same_v<T, Ts> && ...)> {};
Use template recursion:
template<typename T, typename... Rest>
struct is_any : std::false_type {};
template<typename T, typename First>
struct is_any<T, First> : std::is_same<T, First> {};
template<typename T, typename First, typename... Rest>
struct is_any<T, First, Rest...>
: std::integral_constant<bool, std::is_same<T, First>::value || is_any<T, Rest...>::value>
{};
static_assert(is_any<int, char, double, int>::value, "error 1"); // OK
static_assert(is_any<int, char, double, short>::value, "error 2"); // error
In C++17 you have an even nicer solution, using template variables and fold expressions:
template<class T, class... Rest>
inline constexpr bool are_all_same = (std::is_same_v<T, Rest> && ...);
And the usage is also simpler than all other examples:
are_all_same<T, A, B, C>
No ::value, no parentheses!
Something like this. First, a small metaprogramming library, because it adds like 2 lines to do it generically:
template<template<typename,typename>class checker, typename... Ts>
struct is_any_to_first : std::false_type {};
template<template<typename,typename>class checker, typename T0, typename T1, typename... Ts>
struct is_any_to_first<checker, T0, T1, Ts...> :
std::integral_constant< bool, checker<T0, T1>::value || is_any_to_first<checker, T0, Ts...>::value>
{};
Then a 2 line implementation of is_any_same_to_first:
template<typename... Ts>
using is_any_same_to_first = is_any_to_first< std::is_same, Ts... >;
And for completeness, the original is_all, which may also prove useful:
template<template<typename,typename>class checker, typename... Ts>
struct is_all : std::true_type {};
template<template<typename,typename>class checker, typename T0, typename T1, typename... Ts>
struct is_all<checker, T0, T1, Ts...> :
std::integral_constant< bool, checker<T0, T1>::value && is_all<checker, T0, Ts...>::value>
{};
template<typename... Ts>
using is_all_same = is_all< std::is_same, Ts... >;
Live example of the is_all_same.
Note that calling is_any_same_to_first anything less explicit is asking for trouble. 2/3 people who tried to answer this question, including me, assumed that is_same<A,B,C> is true iff all three are the same type!
Using the relaxed C++14 constexpr functions, these kinds of things are much easier to code, and probably much faster to compile as well, so you could write:
template <class T, class ... Candidates>
constexpr bool is_all_same() {
bool pairs[] = {std::is_same<T,Candidates>::value...};
for(bool p: pairs) if(!p) return false;
return true;
}
template <class T, class ... Candidates>
constexpr bool is_any_same() {
bool pairs[] = {std::is_same<T,Candidates>::value...};
for(bool p: pairs) if(p) return true;
return false;
}
This is enabled by the fact that in C++14 constexpr functions can have for loops.
The most generic version that works :
since C++11
without dependencies (no #include <type_traits> needed)
only one name is_same works for n-types (no is_same_all needed)
template <typename First, typename Second, typename ... Next>
struct is_same {
template <typename A, typename B>
struct is_same_min {
enum { value = false };
};
template <typename A>
struct is_same_min<A,A> {
enum { value = true };
};
template <typename X, typename Y>
constexpr static bool check() {
return is_same_min<X,Y>::value;
};
template <typename X, typename Y, typename Z, typename ... K>
constexpr static bool check() {
return is_same_min<X,Y>::value and check<Y, Z, K...>();
};
enum { value = check<First, Second, Next...>() };
};
Just use is_same<T1,T2,T3...>::value