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>
Related
In c++ i want to get the type of the arguments of a function.
The issue is i don't want to get the type for all of the arguments only the ones after the first one
template <typename T>
struct FuncTraits : FuncTraits<decltype(&T::operator())> {};
template <typename C, typename R, typename... Args>
struct FuncTraits<R(C::*)(Args...) const> : FuncTraits<void(*)(Args...)> {};
template <typename... Args> struct FuncTraits<void(*)(Args...)> {
using ArgCount = std::integral_constant<std::size_t, sizeof...(Args)>;
using ArgsType = std::tuple<typename std::decay<Args>::type...>;
};
In this example it gets the type for all of the arguments, but i want something more like this
template <typename T>
struct FuncTraits : FuncTraits<decltype(&T::operator())> {};
template <typename C, typename R, typename... Args>
struct FuncTraits<R(C::*)(int, Args...) const> : FuncTraits<void(*)(int unused, Args...)> {};
template <typename... Args> struct FuncTraits<void(*)(int unused, Args...)> {
using ArgCount = std::integral_constant<std::size_t, sizeof...(Args)>;
using ArgsType = std::tuple<typename std::decay<Args>::type...>;
};
Yet this fails complete to compile.
How do i achieve something like this?
You can add another template type to the base overload of FuncTraits:
#include <iostream>
#include <typeinfo>
struct foo
{
float operator ()(int a, char b, unsigned int c) const { return 0; }
};
template <typename T>
struct FuncTraits : FuncTraits<decltype(&T::operator())> {};
template <typename C, typename R, typename... Args>
struct FuncTraits<R(C::*)(Args...) const> : FuncTraits<void(*)(Args...)> {};
template <typename Arg, typename... Args> struct FuncTraits<void(*)(Arg, Args...)> {
using ArgCount = std::integral_constant<std::size_t, sizeof...(Args)>;
using ArgsType = std::tuple<typename std::decay<Args>::type...>;
};
int main()
{
using FooTraits = FuncTraits<foo>;
std::cout << FooTraits::ArgCount() << '\n'; \\ prints '2'
std::cout << typeid(FooTraits::ArgsType).name() << '\n'; \\ prints 'class std::tuple<char,unsigned int>'
}
Consider the following code:
template <class F, class... Args, class = std::void_t<>>
struct is_invokable
: std::false_type {};
template <class F, class... Args>
struct is_invokable<F, Args..., std::void_t<std::invoke_result_t<F, Args...>>>
: std::true_type {};
The goal is to have a trait that is able to tell whether a callable of type F is invokable with arguments of type Args....
However, it fails to compile because:
error: parameter pack 'Args' must be at the end of the template parameter list
What is the (elegant) way to do this in C++17?
namespace details {
template <class F, class, class... Args>
struct is_invokable : std::false_type {};
template <class F, class... Args>
struct is_invokable<F, std::void_t<std::invoke_result_t<F, Args...>>, Args...>
: std::true_type {};
}
template <class F, class... Args>
using is_invokable=typename ::details::is_invokable<F, void, Args...>::type;
I propose an helper struct (is_invokable_h) and the use of std::tuple to wrap the Args...
Something like
#include <type_traits>
#include <utility>
template <typename, typename, typename = void>
struct is_invokable_h : std::false_type
{};
template <typename F, typename ... Args>
struct is_invokable_h<F, std::tuple<Args...>,
std::void_t<std::invoke_result_t<F, Args...>>>
: std::true_type
{};
template <typename F, typename ... Args>
struct is_invokable : is_invokable_h<F, std::tuple<Args...>>
{};
int foo (int)
{ return 0; }
int main()
{
static_assert( true == is_invokable<decltype(foo), int>{} );
static_assert( false == is_invokable<decltype(foo), int, int>{} );
}
I am trying to implement a mechanism, which would provide me some information about the template argument function type.
Main idea is to get the number of arguments, return type, total sum of sizes of each argument.
I have something running for lambdas based on this entry.
template <typename T, typename... Args>
struct sumSizeOfArgs {
enum { totalSize = sizeof(typename std::decay<T>::type) + sumSizeOfArgs<Args...>::totalSize };
};
template<typename T>
struct sumSizeOfArgs<T> {
enum {totalSize = sizeof(typename std::decay<T>::type)};
};
}
template <typename T>
struct function_traits : public function_traits<decltype(&T::operator())>
{};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>
{
enum { arity = sizeof...(Args) };
typedef ReturnType result_type;
enum { totalSize = sumSizeOfArgs<Args...>::totalSize };
template <size_t i>
struct arg
{
typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
};
};
However, indeed this code does not work for normal functions types such as
function_traits<void()>
it does not have an operator(). I would greatly appreciate, any suggestion to make this code work for both cases.
Thanks,
Slightly improved original part:
#include <tuple>
#include <type_traits>
template <typename... Args>
struct sumSizeOfArgs
{
static constexpr size_t totalSize = 0;
};
template <typename T, typename... Args>
struct sumSizeOfArgs<T, Args...>
{
static constexpr size_t totalSize = sizeof(typename std::decay<T>::type)
+ sumSizeOfArgs<Args...>::totalSize;
};
template <typename T>
struct sumSizeOfArgs<T>
{
static constexpr size_t totalSize = sizeof(typename std::decay<T>::type);
};
template <typename T>
struct function_traits_impl;
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(ClassType::*)(Args...)>
{
static constexpr size_t arity = sizeof...(Args);
using result_type = ReturnType;
static constexpr size_t totalSize = sumSizeOfArgs<Args...>::totalSize;
template <size_t i>
struct arg
{
using type = typename std::tuple_element<i, std::tuple<Args...>>::type;
};
};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(ClassType::*)(Args...) const>
: function_traits_impl<ReturnType(ClassType::*)(Args...)> {};
New part starts here (traits' class partial specialization for functions):
template <typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(Args...)>
{
static constexpr size_t arity = sizeof...(Args);
using result_type = ReturnType;
static constexpr size_t totalSize = sumSizeOfArgs<Args...>::totalSize;
template <size_t i>
struct arg
{
using type = typename std::tuple_element<i, std::tuple<Args...>>::type;
};
};
template <typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(*)(Args...)>
: function_traits_impl<ReturnType(Args...)> {};
Crucial part is here (determining the presence of operator()):
template <typename T, typename V = void>
struct function_traits
: function_traits_impl<T> {};
template <typename T>
struct function_traits<T, decltype((void)&T::operator())>
: function_traits_impl<decltype(&T::operator())> {};
Test:
int main()
{
static_assert(function_traits<void()>::arity == 0, "!");
static_assert(function_traits<void(int)>::arity == 1, "!");
static_assert(function_traits<void(*)(int, float)>::arity == 2, "!");
auto lambda = [] (int, float, char) {};
static_assert(function_traits<decltype(lambda)>::arity == 3, "!");
auto mutable_lambda = [] (int, float, char, double) mutable {};
static_assert(function_traits<decltype(mutable_lambda)>::arity == 4, "!");
}
DEMO 1
Or even simpler, with a single trait class:
#include <tuple>
template <typename ReturnType, typename... Args>
struct function_traits_defs
{
static constexpr size_t arity = sizeof...(Args);
using result_type = ReturnType;
template <size_t i>
struct arg
{
using type = typename std::tuple_element<i, std::tuple<Args...>>::type;
};
};
template <typename T>
struct function_traits_impl;
template <typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(Args...)>
: function_traits_defs<ReturnType, Args...> {};
template <typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(*)(Args...)>
: function_traits_defs<ReturnType, Args...> {};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(ClassType::*)(Args...)>
: function_traits_defs<ReturnType, Args...> {};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(ClassType::*)(Args...) const>
: function_traits_defs<ReturnType, Args...> {};
// + other cv-ref-variations
template <typename T, typename V = void>
struct function_traits
: function_traits_impl<T> {};
template <typename T>
struct function_traits<T, decltype((void)&T::operator())>
: function_traits_impl<decltype(&T::operator())> {};
int main()
{
static_assert(function_traits<void()>::arity == 0, "!");
static_assert(function_traits<void(int)>::arity == 1, "!");
static_assert(function_traits<void(*)(int, float)>::arity == 2, "!");
auto lambda = [] (int, float, char) {};
static_assert(function_traits<decltype(lambda)>::arity == 3, "!");
auto mutable_lambda = [] (int, float, char, double) mutable {};
static_assert(function_traits<decltype(mutable_lambda)>::arity == 4, "!");
struct Functor
{
void operator()(int) {}
};
static_assert(function_traits<Functor>::arity == 1, "!");
}
DEMO 2
Note: Unfortunately none of the above solutions will work for generic lambdas, related discussion is Arity of a generic lambda
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.
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