I am writing an identity function for some of my classes that keeps a count of its calls (long story -> short: metrics).
At the moment, I'm trying to figure the performance differences/benefits of using a template vs auto.
Here is a short example taken from my code of what I'm doing:
namespace Metrics {
unsigned long identifications = 0;
//auto version
auto identity(auto i) {
//... other stuffs
identifications++;
return i;
};
//template version
template<class I> I identity(I i) {
//... other stuffs
identifications++;
return i;
};
};
There's a bit more going on, but that is the basics. I know the compiler will just make a function for each, i.e.
identity(5);
identity("5");
//generates the functions
int identity(int i) { ... return i; };
const char* identity(const char* i) { ... return i; };
At run-time, which one is faster?
And do they have a compile time difference?
Since this function is meant to be called a lot, I'm more interested in run-time performance, but there also could be a large amount of types to generate the function for, so I'm also interested in which one would be faster at compile-time.
auto identity(auto i)
{
//...
return i;
}
is a shorthand for
template <class T>
auto identity(T i)
{
// ...
return i;
}
which in turn is a shorthand for
template <class T>
T identity(T i)
{
// ...
return i;
}
So no difference whatsoever.
Not applicable to your example, but if you are going to use auto parameters you need to be aware of some gotchas:
auto as return type
auto foo(auto a)
Does not mean
// not this
template <class T>
T foo(T a)
The return type will be deduced from the return expression(s) in foo definition, just like any auto return type. It just happens that in your function the return type is deduced to be the same as the parameter type.
Multiple auto parameters
void foo(auto a, auto b)
Is not equivalent to
// not this
template <class T>
void foo(T a, T b)
but with
template <class T, class U>
void foo(T a, U b)
Related
I have the following concept:
template <typename T>
concept FunctorInt = requires(T a, int b) {
a.operator()(b); //require the () operator with a single int parameter.
};
I use this in the following function:
template <FunctorInt functor_t>
void for_each_sat_lit(const int ClauseIndex, functor_t functor) {
auto LitIndex = -1;
uint32_t Count = h_SatisfiedLitCount[ClauseIndex];
if constexpr (!satlit) { Count = h_LiteralsInClauseCount[ClauseIndex] - Count; }
for (uint32_t dummy = 0; dummy < Count; dummy++) {
LitIndex = NextSetBit(h_SATLiteralBits[ClauseIndex], LitIndex);
functor(LitIndex); //LitIndex must be an int.
}
}
This compiles. However, when I try and break the code by changing the concept to
template <typename T>
concept FunctorInt = requires(T a, float b) {
a.operator()(b); //I intend to require the () operator with a single float parameter.
};
It still compiles, meaning it did not constrain the functor at all.
How do I constrain a functor so that it can only have a single int parameter?
MSVC: concepts.cpp
#include <concepts>
template <typename T>
concept FunctorInt = requires(T a, int b) {
a.operator()(b); //require the () operator with a single int parameter.
};
template <typename T>
concept FunctorFloat = requires(T a, float b) {
a.operator()(b); //require the () operator with a single float parameter.
};
void Loop(FunctorInt auto functor) {
for (auto i = 0; i < 10; i++) {
functor(i);
}
}
void LoopShouldNotCompile(FunctorFloat auto functor) {
for (auto i = 0; i < 10; i++) {
functor(i); //<< i is not a float.
}
}
int main(const int argc, const char* argv[]) {
Loop( [](int a){ printf("%i", a); });
LoopShouldNotCompile([](float a){ printf("%f", a); });
}
If I change the definitions of FunctorInt and FunctorFloat using std::invocable, the same problem persists:
concept FunctorInt = std::invocable<int>;
concept FunctorFloat = std::invocable<float>;
Everything still compiles, whereas it should give a compile error on LoopShouldNotCompile.
UPDATE:
I settled on:
template <typename T>
concept FunctorInt =
requires() { [](void(T::*)(int) const){}(&T::operator()); }
|| requires() { [](void(T::*)(int) ){}(&T::operator()); };
Which creates a functor that only allows a single int parameter and doesn't care about const-correctness.
If you want to block a function from accepting any other type that you want, you can use a type matching function template... e.g.
#include <concepts>
template <typename T>
requires std::same_as<T,float>
void func([[maybe_unused]]T f) {}
int main() {
//func(1); // doesn't compile
func(1.0f); // works
//func(1.0); // NB: fails again, because float!=double
}
edit: shorter
void func([[maybe_unused]]std::same_as<float> auto f) {}
Your concept check if the type can be called with an int
but you cannot control promotion/conversion which happens before.
You can check signature of T::operator(), but then previous valid cases (as overload, template function, no exact function but similar (const, volatile, ...)) might no longer work.
For example:
template <typename T>
concept FunctorInt = requires() {
[](void(T::*)(int) const){}(&T::operator());
};
void Loop(FunctorInt auto functor) { /**/ }
int main() {
Loop([](int a){ printf("%i", a); });
Loop([](float a){ printf("%f", a); }); // Not compile
}
Demo
I am writing an identity function for some of my classes that keeps a count of its calls (long story -> short: metrics).
At the moment, I'm trying to figure the performance differences/benefits of using a template vs auto.
Here is a short example taken from my code of what I'm doing:
namespace Metrics {
unsigned long identifications = 0;
//auto version
auto identity(auto i) {
//... other stuffs
identifications++;
return i;
};
//template version
template<class I> I identity(I i) {
//... other stuffs
identifications++;
return i;
};
};
There's a bit more going on, but that is the basics. I know the compiler will just make a function for each, i.e.
identity(5);
identity("5");
//generates the functions
int identity(int i) { ... return i; };
const char* identity(const char* i) { ... return i; };
At run-time, which one is faster?
And do they have a compile time difference?
Since this function is meant to be called a lot, I'm more interested in run-time performance, but there also could be a large amount of types to generate the function for, so I'm also interested in which one would be faster at compile-time.
auto identity(auto i)
{
//...
return i;
}
is a shorthand for
template <class T>
auto identity(T i)
{
// ...
return i;
}
which in turn is a shorthand for
template <class T>
T identity(T i)
{
// ...
return i;
}
So no difference whatsoever.
Not applicable to your example, but if you are going to use auto parameters you need to be aware of some gotchas:
auto as return type
auto foo(auto a)
Does not mean
// not this
template <class T>
T foo(T a)
The return type will be deduced from the return expression(s) in foo definition, just like any auto return type. It just happens that in your function the return type is deduced to be the same as the parameter type.
Multiple auto parameters
void foo(auto a, auto b)
Is not equivalent to
// not this
template <class T>
void foo(T a, T b)
but with
template <class T, class U>
void foo(T a, U b)
I want to write a function in c++ that takes a variable of type int and what it does is that it will define the overloading operator () of a functor and will return that functor as output argument. For example:
template<class Functor>
Functor myFunc(double n)
{
Functor f;
double Functor::operator() (double q)
{ return n*q;}
return Functor;
}
class myClass
{
double operator() ( double q ) const ;
};
Is this proper the way of doing it ?
There's a syntactic sugar for what you're trying to do (wrongly). It's called lambda expressions and this is what it should look like:
auto myFunc(double n)
{
return [n](double q) { return n * q; }
}
If C++11 is not available, you can emulate it like this (which fixes your errors above):
class Functor
{
double m_n;
public:
Functor(double n) : m_n(n) {}
double operator()(double q) const { return m_n * q; }
};
Functor myFunc(double n)
{
return Functor(n);
}
If you wish, you can keep myFunc as a template, but the point is, you can change the behaviour by the functor you pass in, so trying to hardcode operator() inside myFunc does not really make sense, and is not possible.
Making it more generic:
template <typename T>
class Functor
{
T m_n;
public:
Functor(T n) : m_n(n) {}
T operator()(T q) const { return m_n * q; }
};
template <template <typename> class Functor, typename T>
auto myFunc(T n)
{
// we can use perfect forwarding here, but it's far beyond the original question
return Functor<T>(n);
}
Usage:
myFunc<Functor>(2)(3)
Even more generic, for variable amount of parameters captured by a functor (variadic templates):
template <template <typename ...> class Functor, typename ... Ts>
auto myFunc(Ts ... ns)
{
return Functor<Ts...>(ns...);
}
I require a simple way to obtain the count / length / size of an object of class T where T is some sort of collection type, such as a std::map, std::list, std::vector, CStringArray, CString, std::string, …
For most of the standard types, T::size() is the correct answer, for most of the MFC classes T::GetSize() is correct and for CString, it is T::GetLength().
I want to have a like:
template <typename T> auto size(const T & t)
...which evaluates to the correct member function call.
It seems like there should be a simple way to invoke a traits template on T which has a size(const T & t) member, which itself uses SFINAE to exist or not exist, and if it exists, then it is by definition calling an appropriate t.size_function() to return the count of elements in that instance of a T.
I could write an elaborate has_member type-trait template - there are a few examples on stackoverflow - all of them quite convoluted for what seems to me "there must be a simpler approach". With C++ 17, it seems like this issue should be easily and elegantly solved?
These discussions here and here seems to use an inelegant solution with some of the answers using preprocessor macros to get the job done. Is that still necessary?
But... surely, there must be a way to use the fact that calling the correct member function on a T is compilable, and calling the wrong one fails to compile - can't that be used directly to create the correct type traits wrapper for a given type T?
I would like something along the lines of:
template <typename T>
auto size(const T & collection)
{
return collection_traits<T>::count(collection);
}
Where the exact specialization of collection_traits<T> is selected because it is the only one that fits for T (i.e. it calls the correct instance method).
You can use expression SFINAE and multiple overloads.
The idea is as follows: check if x.size() is a valid expression for your type - if it is, invoke and return it. Repeat for .getSize and .getLength.
Given:
struct A { int size() const { return 42; } };
struct B { int getSize() const { return 42; } };
struct C { int GetLength() const { return 42; } };
You can provide:
template <typename T>
auto size(const T& x) -> decltype(x.size()) { return x.size(); }
template <typename T>
auto size(const T& x) -> decltype(x.getSize()) { return x.getSize(); }
template <typename T>
auto size(const T& x) -> decltype(x.GetLength()) { return x.GetLength(); }
Usage:
int main()
{
size(A{});
size(B{});
size(C{});
}
live example on wandbox.org
This solution is easy to extend and seamlessly works with containers that are templatized.
What if a type exposes two getters?
The solution above would result in ambiguity, but it's easy to fix by introducing a ranking/ordering that solves that.
Firstly, we can create a rank class that allows us to arbitrarily prioritize overloads:
template <int N> struct rank : rank<N - 1> { };
template <> struct rank<0> { };
rank<N> is implicitly convertible to rank<N - 1>. An exact match is better than a chain of conversions during overload resolution.
Then we can create a hierarchy of size_impl overloads:
template <typename T>
auto size_impl(const T& x, rank<2>)
-> decltype(x.size()) { return x.size(); }
template <typename T>
auto size_impl(const T& x, rank<1>)
-> decltype(x.getSize()) { return x.getSize(); }
template <typename T>
auto size_impl(const T& x, rank<0>)
-> decltype(x.GetLength()) { return x.GetLength(); }
Finally we provide an interface function that begins the dispatch to the right size_impl overload:
template <typename T>
auto size(const T& x) -> decltype(size_impl(x, rank<2>{}))
{
return size_impl(x, rank<2>{});
}
Using a type like D below
struct D
{
int size() const { return 42; }
int getSize() const { return 42; }
int GetLength() const { return 42; }
};
will now choose the rank<2> overload of size_impl:
live example on wandbox
The simplest solution, IMO, is function overloading.
// Default implementation for std containers.
template <typename Container>
std::size_t size(Container const& c) { return c.size(); }
// Overloads for others.
std::size_t size(CStringArray const& c) { return c.GetSize(); }
std::size_t size(CString const& c) { return c.GetLength(); }
// ... etc.
You need expression SFINAE, and you must play nice with other types which might decide to conform to both interfaces, so study std::size().
The goal is to augment std::size() to work on all types which follow at least one of the conventions, as long as they don't mess up trying to follow any of them.
#include <type_traits>
#include <iterator>
namespace internal {
// Avoid conflict with std::size()
template <class C>
auto size_impl(const C& c, int) -> decltype((void)c.size());
// Avoid conflict with std::size()
template <class T, std::size_t N>
void size_impl(const T (&array)[N], int);
template <class C>
constexpr auto size_impl(const C& c, long)
noexcept(noexcept(c.GetLength()))
-> decltype(c.GetLength())
{ return c.GetLength(); }
template <class C>
constexpr auto size_impl(const C& c, long long)
noexcept(noexcept(c.getSize()))
-> decltype(c.getSize())
{ return c.getSize(); }
};
template <class T>
using enable_if_not_void_t = std::enable_if_t<!std::is_void<T>(), T>;
using std::size;
template <class C>
constexpr auto size(const C& c)
noexcept(noexcept(internal::size_impl(c, 0)))
-> enable_if_not_void_t<decltype(internal::size_impl(c, 0))>
{ return internal::size_impl(c, 0); }
You can get arbitrary levels of precedence for extending things using templates and inheritance:
template <std::size_t N>
struct priority : priority<N - 1> {};
template <>
struct priority<0> {};
Something like the proposed Abbreviated Lambdas for Fun and Profit would greatly simplify things.
I have a problem compiling this code.
All I am trying to do is create a variadic class template that can give me the sum of all elements that are passed in (eg. 1,2,3,4,5,6 should give 21) whether it's int or float. I could basically do it with two function templates recursively for which I'm getting the answer correctly but when I'm implementing it in class it doesn't give me an answer.
template <typename T>
class Myclass
{
public:
T sum;
T func(T A,T... B)
{
sum+=A;
func(B...);
}
T func(T A)
{
sum+=A;
return sum;
}
};
int main()
{
Myclass<int> myclass;
cout<<myclass.func(12,11,11,23);
return 0;
}
Your code does not compile because T... is an invalid variadic expansion, as T is not a parameter pack.
You code has also several other issues. I will address them in the snippet below:
template <typename T>
class Myclass
{
public:
// `sum` needs to be initialized to a value, otherwise its value
// will be undefined.
T sum = 0;
// `TRest...` is a template variadic type pack.
template <typename... TRest>
T func(T A, TRest... B)
{
sum+=A;
// You need to return from the recursive case of `func`.
return func(B...);
}
T func(T A)
{
sum+=A;
return sum;
}
};
working wandbox example
Note that the values matched in TRest... can be of any type. If you want to force them to be T, you can use the following technique (or static_assert):
template <typename...>
using force_to_t = T;
// ...
T func(T A, force_to_t<TRest>... B)
{
sum+=A;
// You need to return from the recursive case of `func`.
return func(B...);
}
I learned this solution thanks to Piotr's answer on another question.
T func(T A,T... B)
{
sum+=A;
func(B...);
}
This is not valid C++ syntax when func is not a function template with T its template parameter pack. ... can only be used to expand packs; T is a non-pack template parameter of the class template.
There are two ways to do this, depending on what you want to achieve.
One: If you want func to accept a mix of arbitrary types, you can make it a (member) function template:
template <typename T>
class Myclass
{
public:
T sum;
template <class F1, class... F>
T func(F1 A, F... B)
{
sum+=A;
func(B...);
return sum;
}
template <class F>
T func(F A)
{
sum+=A;
return sum;
}
};
Two: If you want func to only accept Ts, you can change it to use an initializer list:
template <typename T>
class Myclass
{
public:
T sum;
T func(std::initializer_list<T> A)
{
for (const auto& a : A)
sum+=a;
return sum;
}
};
Note that this will require calling it with a list in braces (e.g. func({1, 2, 42}) instead of func(1, 2, 42), but it's the approach also taken by e.g. std::max.
Notice that there are a few issues in your code unrelated to the question at hand.
One, which I fixed in the example above, is that your first overload of func didn't return anything. Calling it would result in Undefined Behaviour.
Another one, pointed out by #Zereges in the comments, is that T sum is not initialised explicitly. If MyClass is instantiated with a POD type (such as int or double), it will be used uninitialised. You should add a constructor for Myclass:
Myclass() : sum{} {}
You can avoid the need for recursive calls by writing the sequential sum+=A as an initialiser for a std::initializer_list:
template <typename T>
class Myclass
{
template <class... F>
T func_impl(F... A)
{
std::initializer_list<int>{
((void)(sum+=A), 0)...};
return sum;
}
public:
Myclass() :sum(){}
T sum;
template <class F1, class... F>
T func(F1 A, F... B)
{
return func_impl(A, B...);
}
};
You can do that with another approach that avoid recursive call.
template <typename T>
class Myclass
{
public:
T sum;
Myclass() { sum = 0; }
template<typename ...T1>
T func(T1 ... args)
{
auto l_expansion_list =
{
(
[this, &args]()
{
this->sum += args;
return true;
}()
)...
};
return sum;
}
};