How to pass a template function in a template argument list
I suspect the answer is "you cannot do this".
Yes, that is the case, you cannot pass a function template as a template argument. From 14.3.3:
A template-argument for a template template-parameter shall be the
name of a class template or an alias template, expressed as
id-expression.
The template function needs to be instantiated before you pass it to the other template. One possible solution is to pass a class type that holds a static produce_5_function
like so:
template<typename T>
struct Workaround {
static T produce_5_functor() { return T(5); }
};
template<template<typename>class F>
struct client_template {
int operator()() const { return F<int>::produce_5_functor(); }
};
int five = client_template<Workaround>()();
Using alias templates, I could get a little closer:
template <typename T>
T produce_5_functor() { return T(5); }
template <typename R>
using prod_func = R();
template<template<typename>class F>
struct client_template {
int operator()(F<int> f) const { return f(); }
};
int five = client_template<prod_func>()(produce_5_functor);
How to pass a template function as an argument in C++?
You need to specify the template argument for display
explicitly:
iter(arr, 3, display<int>);
Or make iter
taking function pointer:
template <class T_arr>
void iter(T_arr *arr, int len, void (*func)(T_arr))
{
for(int i = 0; i < len; i++)
{
func(arr[i]);
}
}
then you can
iter(arr, 3, display); // template argument gets deduced as int
How to pass a templated class without it's argument list as a template argument?
You can make container
a template template parameter, and you declare createContainer1
twice in main
. This compiles:
#include <iostream>
template <typename T>
class Container1 {};
template <typename T>
class Container2 {};
template <typename type, template<class> class container>
class CreateContainer
{
container<type> createContainer()
{
return container<type>();
}
container<const type> createConstContainer()
{
return container<const type>();
}
};
int main()
{
CreateContainer<int,Container1> createContainer1;
CreateContainer<int,Container2> createContainer2;
}
Note that this assumes that the container
template parameter has a single type parameter. It wont work for eg for a template <typename T,size_t foo> struct container3 {};
, but it could be made to work, if you need that.
Is there any workaround for passing a function template as a template parameter?
You can't pass a templated function as a template argument unfortunately unless you specify the template arguments explicitly, e.g.:
template<auto T>
auto func(auto&&... args) {
return T(std::forward<decltype(args)>(args)...);
}
struct Foo { Foo(int i) {} };
int main() {
auto unique_foo = func<std::make_unique<Foo, int>>(1);
}
You can however pass around templated function objects without problems, so the following would work:
template<class T>
struct unique {
auto operator()(auto&&... args) {
return std::make_unique<T>(std::forward<decltype(args)>(args)...);
}
};
template<class T>
struct shared {
auto operator()(auto&&... args) {
return std::make_shared<T>(std::forward<decltype(args)>(args)...);
}
};
template<template<class> class F, class T, class... Args>
requires std::is_invocable_v<F<T>, Args...>
auto func(Args&&... args) {
return F<T>{}(std::forward<Args>(args)...);
}
struct Foo { Foo(int i) {} };
int main(){
auto foo_unique = func<unique, Foo>(1);
auto foo_shared = func<shared, Foo>(2);
}
godbolt example
If you also need to deduce the template parameters of your class by the parameters passed to std::make_unique
(like in your linked example), you can add an overload for func
that deals with templated types:
template<template<class...> class T, class... Args>
using deduced_type = decltype(T{std::declval<Args>()...});
template<template<class> class F, template<class...> class T, class... Args>
requires std::is_invocable_v<F<deduced_type<T,Args...>>, Args...>
auto func(Args&&... args) {
return F<deduced_type<T, Args...>>{}(std::forward<Args>(args)...);
}
godbolt example
that deduces the template parameters to your type T
based on the passed in parameters.
template<class A, class B>
struct Foo { Foo(A,B) {} };
struct Bar { Bar(int i) {} };
int main(){
// automatically deduces the types for A, B in Foo based on arguments
auto foo_unique = func<unique, Foo>(1, 2);
// the normal overload of func handles non-templated classes:
auto bar_unique = func<unique, Bar>(1);
}
A template function as a template argument
You can't have a template template parameter that accepts function templates, only class templates. Luckily we can make a class that looks rather like a function.
#include <vector>
template <class T>
struct CopyVector { void operator()() { std::vector<T> v; /*...*/} };
template <class T>
struct CopyVectorAsync{ void operator()() { std::vector<T> v; /*...*/} };
template <template <class> class copy>
void Test()
{
copy<char>{}();
copy<short>{}();
copy<int>{}();
}
int main()
{
Test<CopyVector>();
Test<CopyVectorAsync>();
}
Pass a templated function as argument to another function
Function parameters are variables. Not variable templates; just regular old variables. And a non-template variable cannot be given template parameters.
You cannot pass a function template anywhere. You can only pass a particular instantiation of a function template. The closest you can get to what you want is to pass a type that has a templated operator()
overload, but unless you can provide the template parameters through deduction, the only way to invoke it is via fn.operator()<TemplateArguments>(params)
. So you may as well have given it a meaningful name.
Why can't template functions be passed as a template template parameter?
I don't know for sure the answer to the question of why C++ does not provide function template template parameters, but I imagine it has something to do with:
- Any nontrivial change to templates will require complicated analysis to determine what changes need to be made to the standard text
- This feature would be rarely used; after all, class template template parameters are mostly used in partial specializations, i.e., to dispatch on types that are themselves template specializations, and it's rare to want to do that with functions
- It wouldn't make sense to support function template template parameters without also supporting a type of template parameter that would accept any non-template function (we can do this in C++17 with
auto
but this is obviously way too late for C++98 to have function template template parameters) - You can work around the lack of function template template parameters using class templates anyway (sort of like what we do with partial specializations).
- Function overloading complicates things. In the presence of overloading, there's no way to unambiguously name a particular function template. Should one be provided? Or, do we take the point of view that an overload set is meant to be passed as a whole to a function template template parameter? What if overload resolution then selects a non-template overload? How do we even answer these design questions without having a compelling use case?
If you believe that you know how to address all these concerns, and in particular can provide a compelling argument for why we need this feature in the language despite the fact that it would be complicated and we can work around its absence using class template template parameters, feel free to write up a proposal for the standard.
How to pass any number of arguments to C++ template function?
It may be that you are not using the parameter pack in the correct way.
Correct usage:
template <typename T1, typename T2, auto Method, class ...Args>
T1 * wrapObject(Args &&... args)
{
T2 * obj = (*_asposeObj.*Method)(args...);
...
}
With perfect forwarding:
template <typename T1, typename T2, auto Method, class ...Args>
T1 * wrapObject(Args &&... args)
{
T2 * obj = (*_asposeObj.*Method)(std::forward<Args>(args)...);
...
}
Learn more: What are the main purposes of using std::forward and which problems it solves?
Is there a way to pass templated function signature as a template template parameter
In the example below one has a template template parameter that accepts the preferred signature for the function.
Because of the specialization and the lack of a body for the template class, only types for callables are accepted.
It is a generalization of what the OP actually asked:
#include<cassert>
template<typename F>
struct S;
template<typename R, typename... Args>
struct S<R(Args...)> {
using type = R(*)(Args...);
};
template<template<typename> class F>
struct T {
typename F<void(int)>::type ft;
typename F<double(double, double)>::type gt;
};
void f(int) { }
double g(double x, double y) { return x+y; }
int main() {
T<S> t;
t.ft = f;
t.gt = g;
t.ft(42);
auto v = t.gt(1., 1.);
assert(v == 2.);
}
Related Topics
Does Std::Vector *Have* to Move Objects When Growing Capacity? Or, Can Allocators "Reallocate"
Copy Constructor of Template Class
C++ Error: Undefined Reference to 'Main'
Issuing System Commands in Linux from C, C++
Is Std::Vector Copying the Objects with a Push_Back
Dead Code Detection in Legacy C/C++ Project
How to Initialise a Dynamic Array in C++
Is It Legal to Index into a Struct
Std::Map, Pointer to Map Key Value, Is This Possible
Warning: Format Not a String Literal and No Format Arguments
How to Delete an Element from a Vector While Looping Over It
Which Standard Wording Tells Us That Ref-To-Const Temporary Lifetime Extension Only "Works Once"
Why Is This Cin Reading Jammed
What Is Better, Adjacency Lists or Adjacency Matrices for Graph Problems in C++
Common Array Length MACro for C
Are Static Variables in a Base Class Shared by All Derived Classes