Background : I've created the following class C, whose constructor should take N variables of type B& :
class A;
class B
{
A* getA();
};
template<size_t N>
class C
{
public:
template<typename... Args>
inline C(Args&... args) :
member{args.getA()...}
{}
private:
std::array<A*, N> member;
};
Problem : my problem is how to constraint the variadic Args to be all of type B ?
My partial solution : I wanted to define a predicate like :
template <typename T, size_t N, typename... Args>
struct is_range_of :
std::true_type // if Args is N copies of T
std::false_type // otherwise
{};
And redefine my constructor accordingly :
template <typename... Args,
typename = typename std::enable_if<is_range_of_<B, N, Args...>::value>::type
>
inline C(Args&... args);
I've seen a possible solution on this post : https://stackoverflow.com/a/11414631, which defines a generic check_all predicate :
template <template<typename> class Trait, typename... Args>
struct check_all :
std::false_type
{};
template <template<typename> class Trait>
struct check_all<Trait> :
std::true_type
{};
template <template<typename> class Trait, typename T, typename... Args>
struct check_all<Trait, T, Args...> :
std::integral_constant<bool, Trait<T>::value && check_all<Trait, Args...>::value>
{};
So, I could write something like :
template <typename T, size_t N, typename... Args>
struct is_range_of :
std::integral_constant<bool,
sizeof...(Args) == N &&
check_all<Trait, Args...>::value
>
{};
Question 1 : I don't know how to define the Trait, because I need somehow to bind std::is_same with B as first argument. Is there any means of using the generic check_all in my case, or is the current grammar of C++ incompatible ?
Question 2 : My constructor should also accept derived classes of B (through a reference to B), is it a problem for template argument deduction ? I am afraid that if I use a predicate like std::is_base_of, I will get a different instantiation of the constructor for each set of parameters, which could increase compiled code size...
Edit : For example, I have B1 and B2 that inherits from B, I call C<2>(b1, b1) and C<2>(b1, b2) in my code, will it create two instances (of C<2>::C<B1, B1> and C<2>::C<B1, B2>) ? I want only instances of C<2>::C<B, B>.
Define all_true as
template <bool...> struct bool_pack;
template <bool... v>
using all_true = std::is_same<bool_pack<true, v...>, bool_pack<v..., true>>;
And rewrite your constructor to
// Check convertibility to B&; also, use the fact that getA() is non-const
template<typename... Args,
typename = std::enable_if_t<all_true<std::is_convertible<Args&, B&>{}...>>
C(Args&... args) :
member{args.getA()...}
{}
Alternatively, under C++17,
template<typename... Args,
typename = std::enable_if_t<(std::is_convertible_v<Args&, B&> && ...)>>
C(Args&... args) :
member{args.getA()...}
{}
I am afraid that if I use a predicate like std::is_base_of, I will get
a different instantiation of the constructor for each set of
parameters, which could increase compiled code size...
enable_if_t<…> will always yield the type void (with only one template argument given), so this cannot be is_base_ofs fault. However, when Args has different types, i.e. the types of the arguments are distinct, then subsequently different specializations will be instantiated. I would expect a compiler to optimize here though.
If you want the constructor to take precisely N arguments, you can use a somewhat easier method. Define
template <std::size_t, typename T>
using ignore_val = T;
And now partially specialize C as
// Unused primary template
template <size_t N, typename=std::make_index_sequence<N>> class C;
// Partial specialization
template <size_t N, std::size_t... indices>
class C<N, std::index_sequence<indices...>>
{ /* … */ };
The definition of the constructor inside the partial specialization now becomes trivial
C(ignore_val<indices, B&>... args) :
member{args.getA()...}
{}
Also, you do not have to worry about a ton of specializations anymore.
namespace detail {
template <bool...> struct bool_pack;
template <bool... v>
using all_true = std::is_same<bool_pack<true, v...>, bool_pack<v..., true>>;
template<class X> constexpr X implicit_cast(std::enable_if_t<true, X> x) {return x;}
};
The implicit_cast is also in Boost, the bool_pack stolen from Columbo.
// Only callable with static argument-types `B&`, uses SFINAE
template<typename... ARGS, typename = std::enable_if_t<
detail::all_true<std::is_same<B, ARGS>...>>>
C(ARGS&... args) noexcept : member{args.getA()...} {}
Option one, if it's implicitly convertible that's good enough
template<typename... ARGS, typename = std::enable_if_t<
detail::all_true<!std::is_same<
decltype(detail::implicit_cast<B&>(std::declval<ARGS&>())), ARGS&>...>>
C(ARGS&... args) noexcept(noexcept(implicit_cast<B&>(args)...))
: C(implicit_cast<B&>(args)...) {}
Option two, only if they are publicly derived from B and unambiguously convertible:
// Otherwise, convert to base and delegate
template<typename... ARGS, typename = decltype(
detail::implicit_cast<B*>(std::declval<ARGS*>())..., void())>
C(ARGS&... args) noexcept : C(implicit_cast<B&>(args)...) {}
The unnamed ctor-template-argument-type is void in any successful substitution.
Related
The following code complains on the line with dp1 "term does not evaluate to a function taking 0 arguments". I expect that dp1 would match the IsInstantiation specialization of Dispatch, but it errors.
How would I change this code so that it will work as I expect? I am using VS2015 and cannot use std::invoke or std::is_invokable.
#include <type_traits>
template <typename>
class TemplateA {};
struct Callable
{
void operator()() {};
};
template <typename F, typename... Args>
constexpr auto Invoke(F &&f, Args &&... args)
{
return f(std::forward(args)...);
}
template <template<typename...> class TT, typename T>
struct IsInstantiation : std::false_type {};
template <template<typename...> class TT, typename... Ts>
struct IsInstantiation<TT, TT<Ts...>> : std::true_type {};
template <typename, typename = void>
struct HasNoArgs : std::false_type {};
template <typename T>
struct HasNoArgs<T, std::void_t<decltype(Invoke(T{}))>> : std::true_type {};
template <typename T1, typename = void>
class Dispatch;
template <typename T1>
class Dispatch<T1, std::enable_if_t<HasNoArgs<T1>::value>> {};
template <typename T1>
class Dispatch<T1, std::enable_if_t<IsInstantiation<TemplateA, T1>::value>> {};
int main(int argc, char *argv[])
{
Dispatch<TemplateA<int>> dp1;
Dispatch<Callable> dp2;
return 0;
}
There are several problems with your code.
This is an improper use of forward:
return f(std::forward(args)...);
The function parameter for std::forward is a non-deduced context, on purpose. So this call will never succeed. You want f(std::forward<Args>(args)...)
Invoke is SFINAE unfriendly:
template <typename F, typename... Args>
constexpr auto Invoke(F &&f, Args &&... args)
{ ... }
If F is indeed invocable with Args..., this function will work fine. If it isn't, then this is a hard compile error because the problem only surfaces in the body, which is outside of the "immediate context" of the substitution. As a result, it's not a "substitution failure" (the SF in SFINAE), it's an instantiation failure. In HasNoArgs, you're trying to see if you can invoke it - which means you need a substitution failure. To do that, you need to lift the expression into the immediate context:
template <typename F, typename... Args>
constexpr auto Invoke(F &&f, Args &&... args)
-> decltype(f(std::forward<Args>(args)...))
{ return f(std::forward<Args>(args)...); }
Now, it's SFINAE friendly (and additionally, can return a reference).
Your HasNoArgs checks more than you think it does:
template <typename T>
struct HasNoArgs<T, std::void_t<decltype(Invoke(T{}))>> : std::true_type {};
This requires that T can be invoked with no arguments, which after fixing #1 and #2 above, is now possible. But it also requires that T{} be a valid expression. Non-default-constructible callables will fail this test, but not for the reason that the test claims it's looking for. To fix that, use std::declval:
template <typename T>
struct HasNoArgs<T, std::void_t<decltype(Invoke(std::declval<T>()))>> : std::true_type {};
This question follows on from here and is to do with accessing tuple elements when the elements of the tuple are defined by means of a template.
If I have as a means of accessing the contents of a tuple:
#include <cstdint>
#include <type_traits>
#include <tuple>
namespace detail
{
template <typename T, typename... Ts> struct get_index;
template <typename T, typename... Ts>
struct get_index<T, T, Ts...> : std::integral_constant<std::size_t, 0> {};
template <typename T, typename Tail, typename... Ts>
struct get_index<T, Tail, Ts...> :
std::integral_constant<std::size_t, 1 + get_index<T, Ts...>::value> {};
template <typename T>
struct get_index<T> : std::integral_constant<std::size_t, 0> {}; // Not found
template <std::size_t N, typename... Ts>
constexpr
auto
safe_get(const std::tuple<Ts...>& t) noexcept
-> typename std::enable_if<N < sizeof...(Ts), decltype(&std::get<N < sizeof...(Ts) ? N : 0>(t))>::type
{
return &std::get<N>(t);
}
template <std::size_t N, typename... Ts>
constexpr
auto
safe_get(const std::tuple<Ts...>&) noexcept
-> typename std::enable_if<sizeof...(Ts) <= N, nullptr_t>::type
{
return nullptr;
}
}
I want to access the tuple elements here, but where each tuple element is created by means of a template. Thus:
class BaseElement {
public:
virtual int polymorphicFunction() {return 0;};
};
template <uint32_t exampleParameter = 1>
class DerivedElement1 : public BaseElement {
public:
DerivedElement1() : i(exampleParameter) {}
virtual int polymorphicFunction() {return 1;};
uint32_t i; /// just used as a placeholder to demo use of parameter
}
template <uint32_t exampleParameter = 2>
class DerivedElement2 : public BaseElement {
public:
DerivedElement2() : i(exampleParameter) {}
virtual int polymorphicFunction() {return 2;};
uint64_t i; /// just used as a placeholder to demo use of parameter (class is different to DE1)
}
template<typename... systems> // systems will always be of derived class of BaseElement
class System {
System() : subsystems(systems{}...),
pd1(detail::safe_get<detail::get_index<DerivedElement1, systems...>::value>(subSystems)),
pd2(detail::safe_get<detail::get_index<DerivedElement2, systems...>::value>(subSystems))
{} // all variadic elements stored in tuple
const std::tuple<systems...> subSystems;
DerivedElement1<> *pd1;
DerivedElement2<> *pd2;
};
pd1 & pd2 should be set to point to the respective derived elements if they exist when specified in the declaration of System, otherwise they should be set to null.
This works when I do:
System<DerivedElement1<>, DerivedElement2<>> sys; // sys.pd1 points to DerivedElement1<> element of tuple, sys.pd2 points to DerivedElement2<> within tuple
But if I supply a variable to the declaration of System, pd1 & pd2 are both set to nullptr.
System<DerivedElement1<5>, DerivedElement2<6>> sys; // sys.pd1 == nullptr, sys.pd2 == nullptr
How can I get pd1 & pd2 to point to the correct tuple elements please?
Edit to try to be more clear:
Different types, derived from a common class, are stored in a tuple (e.g. DerivedElement1<>, DerivedElement2<6>). I have within the storage class pointers that should point to the derived class elements of the tuple. The set pointer code I have works when I use no template parameters, (i.e. DerivedElement1<> in the example above), but does not when I use a template parameter (e.g. DerivedElement1<5>).
So you need instead of get_index:
namespace detail
{
template <template<typename> class Pred, typename... Ts> struct get_index_if;
template <template<typename> class Pred, typename T, typename... Ts>
struct get_index_if<Pred, T, Ts...> :
std::integral_constant<
std::size_t,
Pred<T>::value ? 0 : 1 + get_index_if<Pred, Ts...>::value>
{};
template <template<typename> class Pred>
struct get_index_if<Pred> : std::integral_constant<std::size_t, 0> {}; // Not found
}
A predicate for your types for get_index_if:
template <typename T> struct is_a_Derived1 : std::false_type {};
template <std::uint32_t N> struct is_a_Derived1<DerivedElement1<N>> : std::true_type {};
template <typename T> struct is_a_Derived2 : std::false_type {};
template <std::uint32_t N> struct is_a_Derived2<DerivedElement2<N>> : std::true_type {};
And finally:
// helper for trailing return type... until C++14
#define Return(Ret) decltype Ret { return Ret; }
template <typename... systems>
class System {
const std::tuple<systems...> subSystems;
public:
constexpr System() : subSystems() {}
auto getDerivedElement1()
-> Return((detail::safe_get<detail::get_index_if<is_a_Derived1, systems...>::value>(subSystems)))
auto getDerivedElement2()
-> Return((detail::safe_get<detail::get_index_if<is_a_Derived2, systems...>::value>(subSystems)))
};
Note: As DerivedElement1<N1> and DerivedElement1<N2> are different types (for N1 != N2), the only possible member type would be he base class.
Here you have getter methods with correct type (or nullptr_t when element is absent).
Note: the given predicate doesn't support derived class of DerivedElement1<N>.
I was wondering if there was any solution to find if a type was a specialization of a template that takes non-type parameters without specifying every type ?
For instance, if have a class like this:
template<typename T, std::size_t R>
struct F {}
For now, I'm using a very specialized traits:
template<template<typename, std::size_t> class TT, typename T>
struct is_2 : std::false_type { };
template<template<typename, std::size_t> class TT, typename V1, std::size_t R>
struct is_2<TT, TT<V1, R>> : std::true_type { };
and used like is_2<F, T>::value. However, this is not practical since, if you add another template parameter, you have to edit your traits. Moreover, if you have several templates of this kind, you need to write a traits for each of them.
Is there any way to make something more practical ? I can use C++14. And I don't mean using a macro to reduce the code amount.
Non-type template parameters are a bit of a red headed stepchild.
There is no "any template parameter is matched, type or not".
If you can modify F, you make it more uniform by wrapping your constants in thin types. So:
template<typename T, class R>
struct F;
template<typename T, std::size_t R>
struct F<T, std::integral_constant<std::size_t, R>> {};
now meta-programs like is can be written uniformly:
template<template<class...>class Template, class T>
struct is_instantiation : std::false_type {};
template<template<class...>class Template, class... Ts>
struct is_instantiation<Template, Template<Ts...>> : std::true_type {};
matching everything.
If you have less control over F, you can either use your approach, or write metaprogram that hoists both a template and an instance of that template into something with type wrappers.
struct meta_F {
template<class T, std::size_t R>using raw_apply=F<T,R>;
template<class T, class R>using apply=raw_apply<T,R::value_type>;
};
template<class meta_Template, class... Args>
struct type_lifted_template {};
template<class T, std::size_t R>
struct type_lifted_template< meta_F, T, std::integral_constant<std::size_t, R> > {
using result = meta_F::template raw_apply<T, R>;
};
template<class T, std::size_t R>
auto type_lift_instance( F<T,R> )
-> type_lifted_template< meta_F, T, std::integral_constant<std::size_t, R> >;
Now, type_lift_instance can be specialized for multiple types, and some decltype magic could be used to extract the type_lifted_template specialization for different types.
All of this is pretty rough. You'd be best, if you are doing lots of meta programming on templates, to just have your templates take uniform type parameters, instead of messing around with this stuff.
template<class meta_F, class C>
struct meta_template_is_lifted : std::false_type {};
template<class meta_F, class...Ts>
struct meta_template_is_lifted<meta_F, type_lifted_template< meta_F, Ts... >> : std::true_type {};
template<class meta_F, class C>
struct meta_template_is : meta_template_is_lifted< meta_F, decltype(type_lift_instance( std::declval<C>() ) ) > {};
this isn't much less typing, but the metafication goes on far away from the is code (or other similar code).
I'm probably using "lift" incorrectly.
If you can modify F and there are no other restrictions you haven't mentioned, the easiest solution would be to add a unique base class:
#include <cstddef>
#include <type_traits>
struct unique_F_base {};
template<typename T, std::size_t R>
struct F : unique_F_base
{
};
template<typename T>
using is_F = std::is_base_of<unique_F_base,T>;
int main()
{
static_assert( !is_F< int >::value, "Oops" );
static_assert( is_F< F<int,42> >::value, "Oops" );
}
I would like to create a compile-type function that, given any callable object f (function, lambda expression, function object, ...) and a type T, evaluates to true, if f can be called with an argument of type T, and false if it cannot.
Example:
void f1(int) { ... }
void f2(const std::string&) { ... }
assert( is_callable_with<int>(f1));
assert(!is_callable_with<int>(f2));
I'm thinking that a clever use of the SFINAE rule could achieve this. Possibly somehow like this:
template<typename T, typename F>
constexpr bool is_callable_with(F&&, typename std::result_of<F(T)>::type* = nullptr) {
return true;
}
template<typename T, typename F>
constexpr bool is_callable_with(F&&) {
return false;
}
But this doesn't work, because if F is callable with T, both overloads participate in the overload resolution and there is an ambiguity. I'd like to rewrite it so in the positive case, the first overload would be picked by the overload resolution over the second one. Not sure if I'm even on the right track here though.
A variant of Paul's answer, but following the standard SFINAE test pattern. Again a generic trait with arbitrary parameter types A...:
struct can_call_test
{
template<typename F, typename... A>
static decltype(std::declval<F>()(std::declval<A>()...), std::true_type())
f(int);
template<typename F, typename... A>
static std::false_type
f(...);
};
template<typename F, typename... A>
using can_call = decltype(can_call_test::f<F, A...>(0));
Then a constexpr function as you requested:
template<typename T, typename F>
constexpr bool is_callable_with(F&&) { return can_call<F, T>{}; }
Check live example.
This will work with functions, lambda expressions, or function objects with arbitrary number of arguments, but for (pointers to) member functions you'll have to use std::result_of<F(A...)>.
UPDATE
Below, can_call has the nice "function signature" syntax of std::result_of:
template<typename F, typename... A>
struct can_call : decltype(can_call_test::f<F, A...>(0)) { };
template<typename F, typename... A>
struct can_call <F(A...)> : can_call <F, A...> { };
to be used like this
template<typename... A, typename F>
constexpr can_call<F, A...>
is_callable_with(F&&) { return can_call<F(A...)>{}; }
where I've also made is_callable_with variadic (I can't see why it should be limited to one argument) and returning the same type as can_call instead of bool (thanks Yakk).
Again, live example here.
I would make a type trait first:
template<class X = void>
struct holder
{
typedef void type;
};
template<class F, class T, class X = void>
struct is_callable_with_trait
: std::false_type
{};
template<class F, class T>
struct is_callable_with_trait<F, T, typename holder<
decltype(std::declval<F>()(std::declval<T>()))
>::type>
: std::true_type
{};
And then if you want, you can turn it into a function:
template<typename T, typename F>
constexpr bool is_callable_with(F&&)
{
return is_callable_with_trait<F&&, T>::value;
}
template<class F, class T, class = void>
struct is_callable_with_impl : std::false_type {};
template<class F, class T>
struct is_callable_with_impl<F,T,
typename std::conditional<
true,
void,
decltype( std::declval<F>() (std::declval<T>()) ) >::type
> : std::true_type {};
template<class T, class F>
constexpr bool is_callable_with(F &&)
{
return is_callable_with_impl< F, T >::value;
}
It is basically the same solution as the one posted by Paul, I just prefer to use conditional<true, void, decltype( ... ) > instead of an holder class to avoid namespace pollution.
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.