Using a templated function as template parameter - c++

I'm writing a class with a function that is repeatedly called and decided to implement this as giving the function as template parameter.
As a concrete example of what I'm talking about, consider the following class:
#include <array>
template<double (*func)(std::array<double,3>)>
class MyClass
{
public:
MyClass()
{
std::array<double,3> v {{0.1,0.2,0.1}};
func(v);
}
};
which can then be instantiated with a function, as for example:
double func(std::array<double,3> x)
{
return x[0]*x[0]+x[1];
}
int main()
{
MyClass<func> entity;
}
However, I need the function to be callable with different types (the operations in the function are of course applicable to all of them), that is I want to have this function templated, as in:
template<typename scalartype, typename vectype>
scalartype func1(vectype x)
{
scalartype res = x[0]*x[0]+x[1];
return res;
}
I can still use this as template parameter, but the function parameter and return type are then fixed in the class. So how can I have the function as templated function available in the class? Such that I can, for example, call it with an std::vector of four integers and have an integer returned.
I tried using template template parameters, but I can't even figure out how to use two template parameters with them (as they only seem to allow the template ... syntax). I'm sorry if this is formulated unclearly, I am still a newcomer.

You can put your template function in a class, and then pass in that class to MyClass.
#include <iostream>
#include <vector>
#include <array>
struct templateHolder {
template <typename vectype, typename scalartype = typename vectype::value_type>
static scalartype func(vectype x) {
return x[0] + x[1];
}
};
template<typename T>
class MyClass
{
public:
MyClass()
{
std::vector<int> vec {1,2};
std::cout << T::func(vec) << std::endl;
std::array<double, 2> arr {0.5, 3.33};
std::cout << T::func(arr) << std::endl;
}
};
int main() {
MyClass<templateHolder> foo;
return 0;
}
I chose to deduce scalartype from vectype. Not necessarily what you want but it could be an option depending on your use-case.

Related

How to initiate std::unique_ptr in the constructor with std::make_unique() [duplicate]

I have a class with a unique_ptr member.
class Foo {
private:
std::unique_ptr<Bar> bar;
...
};
The Bar is a third party class that has a create() function and a destroy() function.
If I wanted to use a std::unique_ptr with it in a stand alone function I could do:
void foo() {
std::unique_ptr<Bar, void(*)(Bar*)> bar(create(), [](Bar* b){ destroy(b); });
...
}
Is there a way to do this with std::unique_ptr as a member of a class?
Assuming that create and destroy are free functions (which seems to be the case from the OP's code snippet) with the following signatures:
Bar* create();
void destroy(Bar*);
You can write your class Foo like this
class Foo {
std::unique_ptr<Bar, void(*)(Bar*)> ptr_;
// ...
public:
Foo() : ptr_(create(), destroy) { /* ... */ }
// ...
};
Notice that you don't need to write any lambda or custom deleter here because destroy is already a deleter.
It's possible to do this cleanly using a lambda in C++11 (tested in G++ 4.8.2).
Given this reusable typedef:
template<typename T>
using deleted_unique_ptr = std::unique_ptr<T,std::function<void(T*)>>;
You can write:
deleted_unique_ptr<Foo> foo(new Foo(), [](Foo* f) { customdeleter(f); });
For example, with a FILE*:
deleted_unique_ptr<FILE> file(
fopen("file.txt", "r"),
[](FILE* f) { fclose(f); });
With this you get the benefits of exception-safe cleanup using RAII, without needing try/catch noise.
You just need to create a deleter class:
struct BarDeleter {
void operator()(Bar* b) { destroy(b); }
};
and provide it as the template argument of unique_ptr. You'll still have to initialize the unique_ptr in your constructors:
class Foo {
public:
Foo() : bar(create()), ... { ... }
private:
std::unique_ptr<Bar, BarDeleter> bar;
...
};
As far as I know, all the popular c++ libraries implement this correctly; since BarDeleter doesn't actually have any state, it does not need to occupy any space in the unique_ptr.
Unless you need to be able to change the deleter at runtime, I would strongly recommend using a custom deleter type. For example, if use a function pointer for your deleter, sizeof(unique_ptr<T, fptr>) == 2 * sizeof(T*). In other words, half of the bytes of the unique_ptr object are wasted.
Writing a custom deleter to wrap every function is a bother, though. Thankfully, we can write a type templated on the function:
Since C++17:
template <auto fn>
struct deleter_from_fn {
template <typename T>
constexpr void operator()(T* arg) const {
fn(arg);
}
};
template <typename T, auto fn>
using my_unique_ptr = std::unique_ptr<T, deleter_from_fn<fn>>;
// usage:
my_unique_ptr<Bar, destroy> p{create()};
Prior to C++17:
template <typename D, D fn>
struct deleter_from_fn {
template <typename T>
constexpr void operator()(T* arg) const {
fn(arg);
}
};
template <typename T, typename D, D fn>
using my_unique_ptr = std::unique_ptr<T, deleter_from_fn<D, fn>>;
// usage:
my_unique_ptr<Bar, decltype(&destroy), destroy> p{create()};
You know, using a custom deleter isn't the best way to go, as you will have to mention it all over your code.
Instead, as you are allowed to add specializations to namespace-level classes in ::std as long as custom types are involved and you respect the semantics, do that:
Specialize std::default_delete:
template <>
struct ::std::default_delete<Bar> {
default_delete() = default;
template <class U>
constexpr default_delete(default_delete<U>) noexcept {}
void operator()(Bar* p) const noexcept { destroy(p); }
};
And maybe also do std::make_unique():
template <>
inline ::std::unique_ptr<Bar> ::std::make_unique<Bar>() {
auto p = create();
if (!p)
throw std::runtime_error("Could not `create()` a new `Bar`.");
return { p };
}
You can simply use std::bind with a your destroy function.
std::unique_ptr<Bar, std::function<void(Bar*)>> bar(create(), std::bind(&destroy,
std::placeholders::_1));
But of course you can also use a lambda.
std::unique_ptr<Bar, std::function<void(Bar*)>> ptr(create(), [](Bar* b){ destroy(b);});
#include "fmt/core.h"
#include <memory>
class example {};
void delete_example(example *)
{
fmt::print("delete_example\n");
}
using example_handle = std::unique_ptr<example, decltype([] (example * p)
{
delete_example(p);
})>;
int main()
{
example_handle handle(new example);
}
Just my two cents, using C++20.
https://godbolt.org/z/Pe3PT49h4
With a lambda you can get the same size as a plain std::unique_ptr. Compare the sizes:
plain: 8
lambda: 8
fpointer: 16
std::function: 40
Which is the output of the following. (I declared the lambda outside the scope of the class. Not sure if you can scope it inside the class.)
#include <iostream>
#include <memory>
#include <functional>
struct Bar {};
void destroy(Bar* b) {}
Bar* create() { return 0; }
auto lambda_destroyer = [](Bar* b) {destroy(b);};
class Foo {
std::unique_ptr<Bar, decltype(lambda_destroyer)> ptr_;
public:
Foo() : ptr_(create(), lambda_destroyer) { /* ... */ }
};
int main()
{
std::cout << "plain: " << sizeof (std::unique_ptr<Bar>) << std::endl
<< "lambda: " << sizeof (std::unique_ptr<Bar, decltype(lambda_destroyer)>) << std::endl
<< "fpointer: " << sizeof (std::unique_ptr<Bar, void(*)(Bar*)>) << std::endl
<< "std::function: " << sizeof (std::unique_ptr<Bar, std::function<void(Bar*)>>) << std::endl;
}
I'm fairly convinced that this is the best current way to do it:
#include <memory>
#include <stdio.h>
template <typename T, auto fn>
struct Deleter
{
void operator()(T *ptr)
{
fn(ptr);
}
};
template <typename T, auto fn>
using handle = std::unique_ptr<T, Deleter<T, fn>>;
using file = handle<FILE, fclose>;
int main()
{
file f{fopen("a.txt", "w")};
return 0;
}
Because you've specified a Functor as the deleter in the unique_ptr's template arguments, you don't need to set a deleter when calling its constructor.
The Deleter functor uses "template auto" to take a deletion function (in this example: fclose) as a template argument, so this needs C++17.
Expanding it to support other types is just one extra "using" line per type.
Simple is also:
class Foo {};
class Bar
{
public:
Bar()
{
// actual initialisation at some point
}
private:
std::unique_ptr<Foo, void(*)(Foo*)> foo = {{}, {}}; // or = {nullptr, {}}
};
Sure, you can also create some helper function to do the job to not have the initial state at any time.
In fact, in your specific scenario, the cleanest way is to actually put your Bar (not mine, sorry for the confusion) into a simple wrapper class, which makes reuse easier.

C++ Template Specialization with non-generic arguments

i have a quiestion regarding template specializations when i have multiple arguments and some of them are non generic
I have a class called Polinom(polynomian) which is basically an array of T objects with a size declared in the template definition(as an int). I also have a class called Complex. Now what I want is to create a template specialization so that I will call different functions(overloaded operator functions) when I have a polinomial with Complex as T. My question is how can I do this, I am getting an error "type name not allowed, stepen undefined" when trying to create the specialization, if someone could clear up what is going on here that would be great.
#pragma once
#include <iostream>
#include <cmath>
using namespace std;
template<class T, int stepen>
class Polinom
{
private:
T koeficijenti[stepen];
public:
Polinom() {};
~Polinom() {};
void ucitajKoef();
T vrednost(T x);
};
template<>
class Polinom<Complex, int stepen> //error type name not allowed
{
};
template<class T, int stepen>
T Polinom<T, stepen>::vrednost(T x)
{
T suma = koeficijenti[1] * (T)pow(x, stepen);
for (int i = 1; i < stepen; i++)
{
suma += koeficijenti[i] * pow(x, stepen - i);
}
return suma;
}
template<class T, int stepen>
void Polinom<T, stepen>::ucitajKoef()
{
T uneseniKoef;
for (int i = 0; i < stepen; i++)
{
cout << "Unesite koeficijent" << endl;
cin >> uneseniKoef;
koeficijenti[i] = uneseniKoef;
}
}
P.S. Is there a workaround to having to rewrite all the other functions of the class since I am only specializing so I can overload the function vrednost(value)
The specialization should look like:
#include <iostream>
template <typename T, int N>
struct Array {
T var[N];
T sum() {
T res{};
for (T v:var) {
res += v;
}
return res;
}
};
struct Complex {};
template <int N>
struct Array<Complex, N> {
Complex var[N];
Complex sum() {
std::cout <<"Complex sum called\n";
return {};
}
};
int main()
{
Array<Complex,5> array;
array.sum();
}
Note that this is a minimal (I think), complete, and verifiable example. You will get better answers if you take the time to create something similar when you ask a question.
To answer your question: I know of no way to simply specialize just one function in a template - which is why you get complex things like the CRTP and individual functions which are invoked from the members (and which can be individually specialized).

Generic vector of templates

For me generic vectors of templates are vector that can take template with any argument list. Like this
vector<Foo<?>> foos;
foos.push_back(Foo<int>(5));
foos.push_back(Foo<Bar>(Bar()));
foos.push_back(Foo<string>("bar"));
EDIT:
This is why I need this
#ifndef EVENT_DISPATCHER_H
#define EVENT_DISPATCHER_H
// #include <boost/signals2.hpp>
#include <string>
#include <vector>
#include <functional>
#include <map>
namespace Whitedrop {
template <typename... T> class EventDispatcher {
public:
EventDispatcher(std::string eventID)
{
}
void on(std::function<void(T...)> callback)
{
mCallbacks.push_back(callback);
}
void trigger(T&... args)
{
for (auto f : mCallbacks)
f(args...);
}
protected:
std::vector<std::function<void(T...)>> mCallbacks;
};
std::map<std::string, EventDispatcher<?> > dispatchers; // HERE <--------
template<typename... T> void registerListener(std::string eventID, std::function<void(T...)> callback)
{
if (!dispatchers.count(eventID))
{
dispatchers[eventID] = new EventDispatcher<T...>(eventID);
return;
}
dispatchers.find(eventID)->second.on(callback);
//std::shared_ptr<Chunk> chunk = mChunks.find(pos)->second;
}
template<typename... T> void invokeListener(std::string eventID, T... args)
{
if (!dispatchers.count(eventID))
{
return;
}
dispatchers.find(eventID)->second->trigger(args...);
}
};
#endif
SInce it seems not possible, how can I resolve my issue?
No, that is not possible. Class templates are templates, not types. The std::vector template requires a type as its first argument, not a template.
You can use class templates to produce types, but you have to choose one particular type for each instantiation of the std::vector template.
More generally, the nature of a template parameter tells you what kind of argument you can use. In C++ there are three "ontological tiers": values ("things that have types), types ("things that are types), and templates ("things that make any of the three"). Each can appear as a template parameter:
template < int A // Value (int prvalue)
, typename B, // Type
, template <typename> class C // Template
> struct Foo {};
Foo<10, double, std::allocator> foo;
// A B C
Simple answer is no.
The compiler needs to figure out types and sizes.
EDIT
Use inheritance
Eg
class Event {
private:
std::string m_id;
public:
Event(std:string &id) : m_id(id) { }
std:string EveentId() const { return m_id;}
virtual void DoEvent() = 0;
};
class MyEvent : Event {
public:
MyEvent() : Event("MyEvent") { }
DoEvent() { std::cout << "MyEvent" << std::endl;
};
Then have a list of events
i.e.
std::vector<std::shard_ptr<Event>> events;
events.push_back<std::make_shared<MyEvent>());
events[0]->DoEvent();
std::vector is a homogeneous container, which means it can only contain one type. Note that Foo<> is a family of types not a single type, the type of std::vector is different depending on the template parameter.
Now, you can achieve what you want using two methods I can think off, the first is by erasing the type, for example you can use std::vector<boost::any>, but note that it completely erases the type (the type info is lost), and is not a compile time operation.
The second way is using a tuple, this is a compile time fixed-size container, which means you can't add new elements at runtime, because the type of each object is determined at compile time.

C++ - Specialize member function for Template Class

I have a class-template representing a mathematical vector:
template<class Value_T, unsigned int N>
class VectorT
{
public:
void Normalize()
{
// normalize only double/float vectors here
}
private:
// elements in the vector
value_type elements[N];
// the number of elements
static const size_type size = N;
};
I would like to have a special treatment for vectors of integer types, as a vector normalization is not possible on this types. So I need a seperate (may be specialization) for the Normalize method that depends on the template argument Value_T of the VectorT class-template.
I have tried to use template specialization in different ways but did not get it to work. Do I have to make the Normalize function a template function itself? At the moment it just a normal member-method.
You can solve this with a tag dispatching technique:
#include <iostream>
#include <type_traits>
template<class Value_T, unsigned int N>
class VectorT
{
public:
void Normalize()
{
using tag = std::integral_constant<bool
, std::is_same<Value_T, double>::value
|| std::is_same<Value_T, float>::value>;
// normalize only double/float vectors here
Normalize(tag());
}
private:
void Normalize(std::true_type)
{
std::cout << "Normalizing" << std::endl;
}
void Normalize(std::false_type)
{
std::cout << "Not normalizing" << std::endl;
}
// elements in the vector
Value_T elements[N];
// the number of elements
static const std::size_t size = N;
};
DEMO
It seems that you want forbid Normalize for other type than floating point, so you may use static_assert to have good error message:
template<class Value_T, unsigned int N>
class VectorT
{
public:
void Normalize()
{
static_assert(std::is_floating_point<Value_T>::value, "Normalize available only for floating point");
// normalize only double/float vectors here
}
// Other stuff
};
Also you can use std::enable_if<>
#include <iostream>
#include <type_traits>
template<class Value_T>
class VectorT
{
public:
template<class T = Value_T>
typename std::enable_if<std::is_integral<T>::value, void>::type
Normalize()
{
std::cout << "Not normalizing" << std::endl;
}
template<class T = Value_T>
typename std::enable_if<!std::is_integral<T>::value, void>::type
Normalize()
{
std::cout << "Normalizing" << std::endl;
}
};
int main()
{
VectorT<int> vint;
VectorT<double> vdouble;
vint.Normalize();
vdouble.Normalize();
return 0;
}
DEMO
Yes, you can independently specialize a specific member function of a template class. However, function templates (including member function templates) do not allow partial specializations. Function templates only support explicit specializations. An explicit specialization in your case that would look as follows
// Header file
template<class Value_T, unsigned int N>
class VectorT
{
public:
void Normalize()
{
// normalize only double/float vectors here
}
...
};
// Declare an explicit specialization for <int, 5>
template <> void VectorT<int, 5>::Normalize();
and then
// Implementation file
// Define the explicit specialization for <int, 5>
template <> void VectorT<int, 5>::Normalize()
{
...
}
However, explicit initialization is not what you need, apparently, since you want to "fix" the type only and leave the size flexible, i.e. you need a partial specialization. This can be done using the std::enable_if functionality of C++11 (as shown in other answers) as well as through some basic tricks of C++98.
Of course if your class is relatively lightweight, i.e. it does not have much generic code besides that Normalize, you can simply partially specialize the whole class. It will take just a bit more typing.

C++ metaprogramming issue/challenge to generate a type based on it function calls

I have a C++ problem. I want to generate a type based on the type arguments passed to a templated function of it.
Let me illustrate it.
class A {
template<class B> M() { }
void Z() {
// NOTE: Here I want to call to X on each type that was feed it to M.
X<N1>();
X<N1>();
...
X<NN>();
}
template<class B> X() { }
};
For example
A a;
a.M<int>();
a.M<double>();
then a.Z() executes ...
X<int>();
X<double>();
Another example to take into account unique types
A a;
a.M<int>();
a.M<int>();
a.M<double>();
a.M<double>();
then a.Z() will still executes ...
X<int>();
X<double>();
Note that I am generating the type A based on the calls to M.
OK! I think that for that class A that's conceptually impossible because A is not templated type and then it can not vary in that way, In fact that's not possible for any type in C++ (I think). But I want you to get the idea.
I am looking forward for a way to confront this problem using meta-programming, but any advice or solution or reference is welcome.
No metaprogramming needed.
class A {
using XPtr = void (A::*)();
std::vector<XPtr> x_calls;
std::set<std::type_index> x_types;
template <typename B> void X() { ... }
public:
template <typename B> void M() {
bool is_new = x_types.insert(std::type_index(typeid(B))).second;
if (is_new)
x_calls.push_back(&A::X<B>);
...
}
void Z() {
for (auto&& ptr : x_calls) {
(this->*ptr)();
}
}
};
First off, I think you're interface isn't really MPL. To be MPL you'd call it more like typedef MyType mpl::vector<int, double> and then find a way to build a type that called X<...> for each type. However...
#include <iostream>
#include <typeinfo>
#include <vector>
#include <functional>
#include <algorithm>
using namespace std;
template< typename T>
void X() {
cout<<typeid(T).name()<<endl;
}
struct A {
vector< function<void(void)> > callbacks;
void z() {
for( auto a : callbacks ) a();
}
template<typename T>
void M() {
callbacks.push_back( [](){ X<T>();} );
}
};
int main() {
A a;
a.M<int>();
a.M<double>();
a.z();
return 0;
}
does what you want.
$ g++ --std=c++11 && ./a.out
i
d
Ss
See it live
You can achieve similar functionality using boost::fusion::set and boost::mpl.
class A {
struct functoid {
template<typename T>
void operator(T t)
{
/* do something */
}
}
template<class B> M() {
boost::mpl::for_each<B>(functoid());
}
}
A a;
a.template M<boost::fusion::set<int, double, ...>>();
But, in this case, you need to know the actual types, or, register some callback in operator().