i want to forward a variadic template pack and another template pack like this:
template<class t, class... targs, class... args_t>
t create(argst_t&&... args)
{
return t<targs...>(std::forward<args_t>(args)...);
}
t is not a templated class, only the constructor is templated.
it is supposed to be called like this:
class a{
public:
template<class... args_t>
a(args_t... args) {}
};
int main()
{
create<a, int, float>(10, 5.5);
}
this should call a::awith the arguments 10 as an integer an 5.5 as a float.
is this possible and if how?
Related
I am trying to create a class template that expects a type and a function pointer as template parameters. The function pointer is expected to be a member function of the type passed in. I want the user of the class template to be able to pass in a void member function of the type passed in. That member function will then be called on instances of the type passed in every time a certain function of the class template is called. It's a bit hard to explain but it's supposed to work sort of like this:
template<Type, Function> // For the purpose of explaining it
class Foo
{
public:
template<Args... args>
void callOnAll(Args... args)
{
for(Type* ptr : ptrs_)
{
ptr->Function(std::forward<Args>(args)...);
}
}
private:
std::vector<Type*> ptrs_;
}
Assuming that something like this is possible (which I realize it might not be), the key would have to be getting the template parameters for the class right, and getting the update function right. This is what I've come up with but I still can't get it to work:
template<typename T, template<typename... Args> void(T::*func)(Args... args)>
class EngineSystem
{
public:
template<typename... Args>
void update(Args... args)
{
for (T* handler : handlers_)
{
((*handler).*func)(std::forward<Args>(args)...);
}
}
private:
std::vector<T*> handlers_;
};
The code above does not compile. It points me to the line where I declare the template parameters for the class, underlines void and says expected 'class' or 'typename'.
Is it clear what I'm trying to achieve, and is it possible?
C++ doesn't allow non-type template template parameters. That means you can't have a parameter-pack for your member-function pointer parameter.
Assuming you're using C++17 or newer, you can use an auto template parameter instead:
template<typename T, auto func>
public:
template<typename... Args>
void update(Args... args)
{
for (T* handler : handlers_)
{
(handler->*func)(std::forward<Args>(args)...);
}
}
private:
std::vector<T*> handlers_;
};
Live Demo
Technically that will accept any object for func, but assuming update is called, then (handler->*func)(std::forward<Args>(args)...) still has to be well-formed or compilation will fail.
If you want compilation to fail even if update never gets called, you could use some type traits and a static_assert (or some SFINAE hackery, if you need it) to ensure that func is actually a pointer to a member function of T:
template <typename T, typename U>
struct IsPointerToMemberOf : std::false_type {};
template <typename T, typename U>
struct IsPointerToMemberOf<T, U T::*> : std::true_type {};
template <typename T, typename U>
struct IsPointerToMemberFunctionOf
: std::integral_constant<
bool,
IsPointerToMemberOf<T, U>::value && std::is_member_function_pointer<U>::value
>
{};
template<typename T, auto func>
class EngineSystem
{
static_assert(IsPointerToMemberFunctionOf<T, decltype(func)>::value, "func must be a pointer to a member function of T");
//...
};
Live Demo
#include <iostream>
#include <vector>
template <typename T, typename... Args>
class EngineSystem
{
public:
EngineSystem(void(T::*fun)(Args... args)): fun(fun)
{
}
void update(Args... args)
{
for (T* handler : handlers_)
{
(handler->*fun)(std::forward<Args>(args)...);
}
}
void push(T* t){
handlers_.push_back(t);
}
private:
void(T::*fun)(Args... args);
std::vector<T*> handlers_;
};
struct A {
int x = 3;
void fn(int a, int b){
std::cout << a << b << x;
}
};
template <typename T, typename... Args>
auto makeEngine(void(T::*fun)(Args... args)){
return EngineSystem<T, Args...>(fun);
}
int main() {
EngineSystem<A, int, int> as(&A::fn);
// or deduce types automatically
auto es = makeEngine(&A::fn);
A a;
es.push(&a);
es.update(1,2);
return 0;
}
https://gcc.godbolt.org/z/Pcdf9K9nz
I have very long parameter pack. I wonder is there any way to store the parameter pack and reuse it later. For example, if there are 2 templates:
template<class ... Types> struct A {};
template<class ... Types> struct B {};
I have a specialized type:
typedef A<int, int, float> A1_t;
Is there any operation can let me create a specialized type B which use the same parameter pack as A1_t? (B<int, int, float>). Is there any method to retrieve the <int, int, float> from A1_t or store it?
I want obtain a specialized type B1_t instead of creating the object of B1_t.
A and B describes completely different concept, so I cannot make B nested inside A.
moreover, I would also like to feed the parameter packs to specialize function templates.
template<class ...Ts>
C<Ts...> func1()
{
}
so I can directly call func1<int, int, float>()
It will be nice if I can do something like this:
template<typename T>
transform<B, T> func1()
{
}
next step would be something similar to this:
template<template<class...Ts> templ>
B<Ts...> func2(Ts ...args)
{
}
So I can do func2<A1_t>(1, 2, 3.0f) directly.
Something like this? Using a type transformation based on partial specialization:
#include<type_traits>
template<template<typename...> class, typename>
struct with_tmpl_args_of;
template<template<typename...> class OtherTmpl, template<typename...> class Tmpl, typename... Args>
struct with_tmpl_args_of<OtherTmpl, Tmpl<Args...>> {
using type = OtherTmpl<Args...>;
};
template<template<typename...> class OtherTmpl, typename T>
using with_tmpl_args_of_t = typename with_tmpl_args_of<OtherTmpl, T>::type;
// example
template<class ... Types> struct A {};
template<class ... Types> struct B {};
using A1_t = A<int, int, float>;
using B1_t = with_tmpl_args_of_t<B, A1_t>;
// test
static_assert(std::is_same_v<B1_t, B<int, int, float>>);
This is limited to class templates that do not use non-type template arguments. There is currently unfortunately no way to define template template parameters which accept both type and non-type template parameters in the same template template parameter's parameter.
Also beware of default arguments. This will not use OtherTmpl's default arguments, if one of Tmpl's default arguments matches that position in the template list and will fail if Tmpl's template list (including defaulted arguments) is larger than OtherTmpls.
Regarding the additional examples in your edit:
The second example works directly with the type transform I defined above:
template<typename T>
with_tmpl_args_of_t<B, T> func1()
{
}
The third one can be done like this:
template<typename A, typename... Ts>
with_tmpl_args_of_t<B, A> func2(Ts... args)
{
}
It guarantees that the return type has the same template arguments as A1_t, but it does accept all types as arguments, even if they don't match the types in the template arguments of A1_t. This should not usually be a problem. If the types are not convertible to the correct ones you will get an error at the point where you try the conversion.
If you must take the exact same types as in the template arguments of A1_t for function parameters, you can do something like (untested):
template<typename T>
struct func_with_tmpl_args_of;
template<template<typename...> class Tmpl, typename... Args>
struct func_with_tmpl_args_of<Tmpl<Args...>> {
template<typename F>
struct inner {
constexpr inner(F f) : f(std::move(f)) {}
constexpr static decltype(auto) operator()(Args... args) const {
return f(std::forward<Args>(args)...);
}
private:
F f;
};
};
// example
template<typename T>
constexpr inline auto func2 = func_with_tmpl_args_of<T>::inner{[](auto... args)
-> with_tmpl_args_of_t<B, T> {
// actual function body
}};
when attempting to get functions' signatures when they are input into templates its fairly easy, just do the following:
template <class OutType, class... ArgTypes>
void foo(OutType (*func)(ArgTypes...));
it is only marginally more complicated to get a non-static member function:
template <class OutType, class MemberOf, class... ArgTypes>
void foo(OutType (MemberOf::*func)(ArgTypes...));
// or
template <class OutType, class MemberOf, class... ArgTypes>
void foo(OutType (MemberOf::*func)(ArgTypes...) const);
but how exactly do you combine the two function declarations above into one when it doesn't matter whether or not the input method is const?
Unfortunately, the presence or absence of const on a non-static member function is not a feature that can be deduced separately from the function type it appertains to. Therefore, if you want to write a single foo template declaration that is limited to accepting pointers to members (but accepts both const and non-const member functions) then it would have to be:
template <class MemberOf, class F>
void foo(F MemberOf::*func);
For example:
#include <type_traits>
template <class MemberOf, class F>
void foo(F MemberOf::*func) {
static_assert(std::is_same<F, void(int) const>::value);
}
struct S {
void bar(int) const {}
};
int main() {
foo(&S::bar);
}
You cannot have F's argument types deduced at that point. You would have to dispatch to a helper function. (But we cannot deduce all the types at once while also writing a single declaration that accepts both const and non-const. If that's the only thing you'll accept, then sorry, it's not possible.) We can do this like so:
template <class T>
struct remove_mf_const;
template <class R, class... Args>
struct remove_mf_const<R(Args...)> {
using type = R(Args...);
};
template <class R, class... Args>
struct remove_mf_const<R(Args...) const> {
using type = R(Args...);
};
template <bool is_const, class F, class OutType, class MemberOf, class... ArgTypes>
void foo_helper(F func, OutType (MemberOf::*)(ArgTypes...)) {
// now you have all the types you need
}
template <class MemberOf, class F>
void foo(F MemberOf::*func) {
static_assert(std::is_function<F>::value, "func must be a pointer to member function");
using NonConstF = typename remove_mf_const<F>::type;
constexpr bool is_const = !std::is_same<F, NonConstF>::value;
foo_helper<is_const>(func, (NonConstF MemberOf::*)nullptr);
}
Coliru link
I have a template class that accepts a variable number of types as arguments. The constructor accepts a pointer to an instance of the class that uses Args... - 1 as parameter type. Searching over the internet I found out that a std::tuple is often used to handle this type of problems, but I don't understand how I could take the template arguments, create a tuple, remove the last type and then unpack the tuple again and store the result in a variable that can be retrieved later by the parent() function.
template<typename ...Args>
class MyClass
{
public:
MyClass(MyClass<Args...> *parent) : parent_(parent) // Should be Args - 1
{
}
MyClass<Args...>* parent()
{
return parent_;
}
private:
MyClass<Args...> *parent_;
};
I found different answers here on StackOverflow about similar topics that involve tuples. This code has been posted on another question and should get a tuple with all parameters except the last one. The problem is that I don't know how to adapt it to unpack that tuple again.
template<typename, typename>
struct concat_tuple { };
template<typename... Ts, typename... Us>
struct concat_tuple<std::tuple<Ts...>, std::tuple<Us...>>
{
using type = std::tuple<Ts..., Us...>;
};
template <class T>
struct remove_last;
template <class T>
struct remove_last<std::tuple<T>>
{
using type = std::tuple<>;
};
template <class T, class... Args>
struct remove_last<std::tuple<T, Args...>>
{
using type = typename concat_tuple<std::tuple<T>, typename remove_last<std::tuple<Args...>>::type>::type;
};
#include <type_traits>
#include <tuple>
#include <utility>
#include <cstddef>
template <template <typename...> class C, typename... Args, std::size_t... Is>
auto pop_back(std::index_sequence<Is...>) noexcept
-> C<std::tuple_element_t<Is, std::tuple<Args...>>...>&&;
template <typename... Args>
class MyClass
{
using Parent = std::remove_reference_t<
decltype(pop_back<::MyClass, Args...>(std::make_index_sequence<sizeof...(Args) - 1>{}))
>;
public:
explicit MyClass(Parent* parent) : parent_(parent)
{
}
Parent* parent()
{
return parent_;
}
private:
Parent* parent_;
};
template <>
class MyClass<> {};
int main()
{
MyClass<> a;
MyClass<int> b(&a);
MyClass<int, char> c(&b);
MyClass<int, char, float> d(&c);
}
DEMO
The answer for the previous question, before the edit:
#include <tuple>
#include <utility>
#include <cstddef>
template <typename... Args>
class MyClass
{
public:
auto newInstance()
{
return newInstance(std::make_index_sequence<sizeof...(Args) - 1>{});
}
private:
template <std::size_t... Is>
MyClass<typename std::tuple_element<Is, std::tuple<Args...>>::type...> newInstance(std::index_sequence<Is...>)
{
return {};
}
};
DEMO 2
Why the pop_back function has no body?
This is actually a trait implemented in terms of a function declaration. Alternatively, you could use a more classic solution with a structure specialization:
template <typename T, typename S>
struct pop_back;
template <template <typename...> class C, typename... Args, std::size_t... Is>
struct pop_back<C<Args...>, std::index_sequence<Is...>>
{
using type = C<std::tuple_element_t<Is, std::tuple<Args...>>...>;
};
and then use:
using Parent = typename pop_back<MyClass, std::make_index_sequence<sizeof...(Args) - 1>>::type;
That is, I used a function declaration to shorten the syntax. And it doesn't require a body, since noone is supposed to call this function in an evaluated context.
Why are you using noexcept?
Imagine you have a function:
void foo(MyClass<int, char>) noexcept {}
And elsewhere you want to check whether the call is noexcept:
static_assert(noexcept(foo(pop_back<MyClass, int, char, float>(std::index_sequence<0, 1>{}))), "!");
Without the noexcept specifier, the above assertion would fail, since the call to pop_back would be considered as possibly throwing code.
I am writing Monitor class for synchronization problem and I would like to implement an 'Entry' class that will wrap a std::function.
I implemented it a bit, used function traits, but right now I am only able to construct Entry objects using prepared std::function object. Attempts to write a constructor that has an plain function as a parameter failed with compiler messages about template argument deduction/substitution and <anonymous> parameter.
The program is working but I am just curious how to implement given constructor, this is my code:
template <class F>
struct FunctionType;
template <class R, class Object, class... Args>
struct FunctionType<R (Object::*)(Args...)> {
typedef R return_type;
};
template <class R, class Object, class... Args>
struct FunctionType<R (Object::*)(Args...) const> {
typedef R return_type;
};
template <class F> class Entry {
std::function<F> internalFunction;
...
public:
template <F> Entry(const F& function){
// It doesn't work.
}
template <F> Entry(const std::function<F> function) :
internalFunction(function) {
}
template<F, class... Arguments>
typename FunctionType<F>::return_type operator()(Arguments... arguments){
return internalFunction(arguments...);
}
};
A couple of things:
template<F>
doesn't make any sense at all. You get the type of F from the template parameter on the class, use that and remove this altogether.
Next, it's probably easier for you to use a trailing return type on your operator() function:
template<class... Arguments>
auto operator()(Arguments... arguments) -> decltype(internalFunction(arguments...))
{
return internalFunction(arguments...);
}
(If you have C++14 you can just use auto).
Live Demo
Here's your fixed class
template <class F> class Entry {
std::function<F> internalFunction;
public:
Entry(const F& function){
// It doesn't work.
}
Entry(const std::function<F> function) :
internalFunction(function) {
}
template<class... Arguments>
auto operator()(Arguments... arguments) -> decltype(internalFunction(arguments...)){
return internalFunction(arguments...);
}
};