Suppose an algorithm that has a policy FooPolicy. Policy classes that implement this policy feature a static member function foo, but, for some of them, foo takes an int argument, while for others it does not. I am trying to enable the use of these policy classes with differing interfaces by means of constexpr static data members:
struct SimpleFoo {
static constexpr bool paramFlag = false;
static void foo() {
std::cout << "In SimpleFoo" << std::endl;
}
};
struct ParamFoo {
static constexpr bool paramFlag = true;
static void foo(int param) {
std::cout << "In ParamFoo " << param << std::endl;
}
};
template <typename FooPolicy>
struct Alg {
void foo() {
if (FooPolicy::paramFlag) FooPolicy::foo(5);
else FooPolicy::foo();
}
};
int main() {
Alg<ParamFoo> alg;
alg.foo();
return 0;
}
This code does not compile. gcc 4.8.2 gives the error:
no matching function for call to ‘ParamFoo::foo()’
else FooPolicy::foo();
The else clause gets compiled despite the fact that it is known at compile time that FooPolicy::paramFlag is true. Is there a way to make it work?
Is there a way to make it work?
One solution is to use tag-dispatching:
#include <type_traits>
template <typename FooPolicy>
struct Alg {
void foo() {
foo(std::integral_constant<bool, FooPolicy::paramFlag>{});
}
private:
void foo(std::true_type) {
FooPolicy::foo(5);
}
void foo(std::false_type) {
FooPolicy::foo();
}
};
DEMO
You could dispense with the flag entirely and use expression SFINAE:
template <typename FooPolicy>
struct Alg {
template <typename T=FooPolicy> //put FooPolicy in immediate context
//SFINAEd out if that call is not valid
auto foo() -> decltype(T::foo(),void()) {
FooPolicy::foo();
}
template <typename T=FooPolicy>
auto foo() -> decltype(T::foo(0),void()) {
FooPolicy::foo(6);
}
};
Related
I have this minimal class to represent an event which client can subscribe to.
The event can have an data type associated to it, so when it is triggered by a publisher, an argument of that type would be passed to the client's callback:
template<typename Arg, typename Callback = function<void(const Arg&)>>
class Event
{
public:
Event(Callback c) : mCallback(c){}
void Trigger(const Arg& arg) {
mCallback(arg);
}
private:
Callback mCallback;
};
Now I can create an Event<int> or any other concrete type, but it is really important to me to also allow "empty" event, which has no data associated with it: Event<void>
But sadly that doesn't work:
static void FooVoid() {
cout << "Look ma, no args!" << endl;
}
static void FooInt(int a) {
cout << "int arg " << a << endl;
}
int main()
{
/* Compiles */
Event<int> eInt(&FooInt);
eInt.Trigger(42);
/* Does not compile :(
Event<void> eVoid(&FooVoid);
eVoid.Trigger();
*/
return 0;
}
Is there any way to achieve this desired API? How?
(P.S the solution should work on C++11)
The quickest way of solving this without explicitly specializing for void is to use a parameter pack (added in C++11) for your template argument instead of a single type and using an empty parameter pack instead of void. A parameter pack can homogeneously hold any number of type, including 0 and 1. Then it can be used to generate the right types and member functions. You basically just have to add ... correctly near every use of Arg (link) :
#include <functional>
#include <iostream>
template<typename ... Arg>
class Event
{
public:
using Callback = std::function<void(const Arg&...)>;
Event(Callback c) : mCallback(c){}
void Trigger(const Arg& ... arg) {
mCallback(arg...);
}
private:
Callback mCallback;
};
static void FooVoid() {
std::cout << "Look ma, no args!" << std::endl;
}
static void FooInt(int a) {
std::cout << "int arg " << a << std::endl;
}
int main()
{
/* Compiles */
Event<int> eInt(&FooInt);
eInt.Trigger(42);
Event<> eVoid(&FooVoid);
eVoid.Trigger();
return 0;
}
This has the added benefit that you can use callbacks with more than one argument. If this isn't desirable you can add a static_assert to prevent it :
template<typename ... Arg>
class Event
{
public:
using Callback = std::function<void(const Arg&...)>;
static_assert(sizeof...(Arg) <= 1, "Too many arguments");
Event(Callback c) : mCallback(c){}
void Trigger(const Arg& ... arg) {
mCallback(arg...);
}
private:
Callback mCallback;
};
Notice that this solution requires Event<> instead of Event<void>. You can solve that by adding a short specialization for Event<void> that uses Event<> (link) :
template<>
class Event<void> : public Event<>
{
// Inherit constructors
using Event<>::Event;
};
Is it somehow possible to call every instantiation of a template function without knowing what will get instantiated at write-code-time?
#include <iostream>
template<typename T>
void print_size_of()
{
std::cout << sizeof(T) << "\n";
}
int main()
{
print_size_of<int>();
print_size_of<double>();
//won't work but maybe it shows what i want to do:
template<typename T>
print_size_of<T>();
//is there a syntax so that the compiler replaces that with `print_size_of<int>(); print_size_of<double>();`
}
This is possible; you need to add some static variable inside the function template body to record those instantiations.
In the code below, every instantiated function will have a static variable, whose constructor will register the function pointer to a global registration center:
std::vector<void(*)()> funcs;
struct helper {
explicit helper(void (*f)()) { funcs.push_back(f); }
};
template<typename T>
void print_size_of()
{
static helper _(&print_size_of<T>);
std::cout << sizeof(T) << "\n";
}
int main()
{
print_size_of<int>();
print_size_of<double>();
std::cout << "All instantiation:\n";
for ( auto f : funcs ) {
f();
}
}
EDIT:
This is not strictly recording instantiation. It only records those being called before. If you instantiate it by other methods like taking its address:
void (*f)() = &print_size_of<short>;
but don't call it, then this function pointer won't be registered.
EDIT2:
In fact, it is possible to faithfully record all instantiations. The key point is to associate the instantiation of the function template to the instantiation of a class template. Then a static member of that class will be guaranteed to initialize before entering main() function.
// this one is to make sure `funcs` is initialized
auto &get_funcs() {
static std::vector<void(*)()> funcs;
return funcs;
}
template<void (*f)()>
struct helper {
helper() { get_funcs().push_back(f); }
// this is a static class member, whose initialization is before main()
static helper _ins;
};
template<void (*f)()> helper<f> helper<f>::_ins;
template<typename T>
void print_size_of()
{
// force instantiation of a class
const void *_ = &helper<&print_size_of<T>>::_ins;
std::cout << sizeof(T) << "\n";
}
int main()
{
print_size_of<int>();
print_size_of<double>();
void (*f)() = &print_size_of<short>;
std::cout << "All instantiation:\n";
for ( auto f : get_funcs() ) {
f();
}
}
No, that is not possible.
You can get close by calling every instantiation which was already called once (Use a static variable to register on first call), but that's the best you can do.
I am using c++14 and I have a use case where I have to effectively do this:
template <typename F>
void foo (F&& fun)
{
auto l = []()->int
{
return 20;
};
fun(l);
}
int main ()
{
auto l = [] (auto& a)
{
std::cout << "Hello function: " << a() << std::endl;
// 'a' has to be copied to a queue optionally
};
foo(l);
}
But the foo() in-turn calls a million function - which uses the callback 'fun'. I cannot put all the code in header file. The simplest way to keep the definition of foo() and the called functions in dot cpp file might be to change foo() to
void foo (std::function< void(std::function<int(void)>) > fun)
But this is too inefficient, I dont want any memory allocation. Here there will be many, one of the creating the 'fun' and then for every call to 'fun(...)'. Now the outer std::function can be optimized by using something like the function_ref mentioned here.
https://vittorioromeo.info/index/blog/passing_functions_to_functions.html#fn_view_impl
But inner std::function, cannot be because it has to be 'optionally' copied to a queue. Now how can I make this work without a memory allocation - as close to the performance as using the template. [ One way is to have something like the std::function with a fixed internal storage.] But I have a feeling there exists a way by throwing more templates to achieve what I want. Or some way to change the interface to have more of less same effect.
Not sure if this is what you're looking for, but maybe it can be to some help.
#include <iostream>
#include <deque>
#include <memory>
struct lambdaHolderBase {
virtual int operator()() = 0;
};
template <typename T>
struct lambdaHolder : lambdaHolderBase {
lambdaHolder(T tf) : t(tf) {}
T& t;
int operator()() override { return t(); }
};
template <typename F>
void foo (F&& fun)
{
auto l = []()->int
{
return 20;
};
lambdaHolder<decltype(l)> l2(l);
fun(l2);
}
int main ()
{
auto l = [] (auto& a)
{
static std::deque<lambdaHolderBase*> queue;
std::cout << "Hello function: " << a() << std::endl;
queue.emplace_back( &a );
// 'a' has to be copied to a queue optionally
};
foo(l);
}
I am trying to design a class which all its data is constant and know at compile time. I could just create this by manually typing it all but I want to use a template so that I don't have to rewrite almost the same code many times.
I was thinking templates are the way to do this e.g
template<class T> class A { ... }
A<float>
A<MyObject>
A<int>
But then I wasn't sure how I could get the constant data that I know into this object. I could do it at run-time with a member function which does a switch statement on the type or something similar but I ideally want it to effectively be a dumb data holder for me to use.
So in the case of A<float> I would have this:
// member function
int getSize() {
return 4;
}
Instead of (pseudo code)
// member function
int getSize() {
if (type == float) {
return 4;
} else if ...
}
I'm wondering if there is a known way to do this? I don't have any experience with constexpr, could that be the key to this?
edit: To clarify: I want member functions which always return the same result based on the templated type/class. For example, A would always return 4 from getSize() and 1 from getSomethingElse() and 6.2 from getAnotherThing(). Where as A would return 8 from getSize() and 2 from getSomethingElse() and 8.4 from getAnotherThing().
You can have this template
template <int size_, int foo_, int bar_>
struct MyConstData {
static const int size = size_; // etc
};
Then specialize your template:
template <class T> class A;
template <> class A<float> : MyConstData<13,42,-1> {};
template <> class A<double> : MyConstData<0,0,42> {};
You can specialize particular functions within a class, and given your description of things, I suspect that's what you want. Here is an example of how this works:
#include <iostream>
#include <string>
template <class T>
class A {
public:
int MyConstantFunction() const { // Default implementation
return 0;
}
};
template <>
int A<int>::MyConstantFunction() const
{
return 3;
}
template <>
int A<float>::MyConstantFunction() const
{
return 5; // If you examine the world, you'll find that 5's are everywhere.
}
template <>
int A<double>::MyConstantFunction() const
{
return -5;
}
int main(int, char *[])
{
using ::std::cout;
A<int> aint;
A<float> afloat;
A<long> along;
cout << "aint.MyConstantFunction() == " << aint.MyConstantFunction() << '\n';
cout << "afloat.MyConstantFunction() == "
<< afloat.MyConstantFunction() << '\n';
cout << "along.MyConstantFunction() == "
<< along.MyConstantFunction() << '\n';
return 0;
}
Notice how along just used the default implementation from the class declaration. And this highlights a danger here. If the translation unit using your specialization for a given type hasn't seen that specialization, it won't use it, and that may cause all kinds of interesting problems. Make sure this happens.
The other option is to not provide a default implementation at all, and so you get an instantiation error.
My gut feeling is that you are doing something that is pointless and a poor design. But, since I don't know the full context I can't say that for sure. If you insist on doing this, here's how.
If you want to implement different things depending on the type, you could try this:
template <class T>
class Foo {
T data;
string toString() {
return myGeneralToString(data);
}
};
template <>
class Foo<string> {
string data;
string toString() {
return "Already a string: " + data;
}
};
If you just want templated constants, I'd try this:
template <int a, int b>
class Calc {
public:
static constexpr int SUM = a + b;
};
int main()
{
std::cout << Calc<3, 5>::SUM << std::endl;
return 0;
}
Edit: as pointed out by Omnifarious C++14 has templated constants without templating the class itself. So you could simplify the example to:
class Calc {
public:
template <int a, int b>
static constexpr int SUM = a + b;
};
int main()
{
std::cout << Calc::SUM<3, 5> << std::endl;
return 0;
}
How can I iterate over all base classes of a variadic template class and call a function for each of them.
Here is a minimal example:
struct A { void foo() { std::cout << "A" << std::endl; } };
struct B { void foo() { std::cout << "B" << std::endl; } };
struct C { void foo() { std::cout << "C" << std::endl; } };
template<typename... U>
struct X : public U...
{
void foo() {
static_cast<U*>(this)->foo()...; // ??? should call `foo` for all `U`
}
};
int main() {
X<A,B,C> x;
x.foo();
}
You can't normally without C++17's fold expressions. The ellipsis going there is not valid and the ellipsis going after the asterisk would create a list of pointer template arguments. For the appropriate pattern to be repeated, the ellipsis would have to be at the end of the statement, and that doesn't work here. I found this article to be a good resource for pack expansion.
Instead, there is a trick for it that doesn't require building up any recursive things:
int arr[] = {(static_cast<U*>(this)->foo(), 0)...};
This calls each function and then uses the result with the comma operator to produce the needed ints. Unfortunately, this might result in an unused variable warning. One minimal way around this is to use a std::array (or some class that can be initialized with an initializer list) and cast the result of creating an unnamed one of those to void (casting to void being a somewhat common technique for preventing the warning in general).
Here is a way:
struct thru{template<typename... A> thru(A&&...) {}};
struct A { void foo() { std::cout << "A" << std::endl; } };
struct B { void foo() { std::cout << "B" << std::endl; } };
struct C { void foo() { std::cout << "C" << std::endl; } };
template<typename... U>
struct X : public U...
{
void foo() { thru{(U::foo(), 0)...}; }
};
But if you care about the order of calls, watch out for the known gcc bug as discussed here.