Is there a concise way to point to all instances of a templated function without using macros?
I have several templated functions that I want to test across a variety of types:
template<typename T>
void function1() {
return;
}
template<typename T>
void function2() {
return;
}
template<typename T>
void function3() {
return;
}
I can do this with a macro:
#define TEST_ACROSS_TYPES(fn) \
fn<int>(); \
fn<bool>(); \
fn<char>(); \
fn<double>(); \
TEST_ACROSS_TYPES(function1);
TEST_ACROSS_TYPES(function2);
But, (1) Macros are ugly and hard for others to follow, and (2) I'm using CATCH, which doesn't play nice when using macros to set up test cases.
Is there a way to do something like this:
void testAcrossTypes(SomeType f) {
f<int> ();
f<bool> ();
f<char> ();
f<double> ();
}
which seems much cleaner, except for the problem of defining SomeType. This question (How to define typedef of function pointer which has template arguments) explains how to define a pointer to a templated function; but, requires that the template arguments be specified.
For clarification: Imagine function1, function2, and function3 each test a different templated function. Each function needs to be tested for int, byte, char, double, etc. I want to avoid having to explicitly set up many (i.e. num_functions * num_types) tests for each function. Instead, I want to have a single method that points to the test function (function1, function2, etc.) and runs it for each template type, thus consolidating
function1<int>();
function1<byte>();
function1<char>();
function1<double();
...
function2<int>();
function2<byte>();
function2<char>();
function2<double();
...
function3<int>();
function3<byte>();
function3<char>();
function3<double();
...
into just one call per test function
testAcrossTypes(function1);
testAcrossTypes(function2);
testAcrossTypes(function3);
What you are trying to accomplish with
void testAcrossTypes(SomeType f) {
f<int> ();
f<bool> ();
f<char> ();
f<double> ();
}
would be possible if SomeType could be a template template argument. However, the standard does not allow function templates as template template argument.
From the C++11 Standard:
14.3.3 Template template arguments
1 A template-argument for a template template-parameter shall be the name of a class template or an alias template, expressed as id-expression.
Your best option is to use functors instead of functions. Example:
template<typename T>
struct function1
{
void operator()() {
return;
}
};
template<typename T>
struct function2
{
void operator()() {
return;
}
};
template < template <typename> class F>
void testAcrossTypes() {
F<int>()();
F<bool>()();
F<char>()();
F<double>()();
}
int main()
{
testAcrossTypes<function1>();
testAcrossTypes<function2>();
}
You can accomplish it by means of a type-erased functor, like the one in the following example:
#include<vector>
template<typename T>
void function1() { }
template<typename T>
void function2() { }
template<typename T>
void function3() { }
struct Test {
template<typename T>
static void proto() {
function1<T>();
function2<T>();
function3<T>();
}
void operator()() {
for(auto &f: vec) f();
}
template<typename... T>
static Test create() {
Test test;
int arr[] = { (test.vec.emplace_back(&proto<T>), 0)... };
(void)arr;
return test;
}
using func = void(*)(void);
std::vector<func> vec;
};
void testAcrossTypes(Test test) {
test();
}
int main() {
testAcrossTypes(Test::create<int, bool, char, double>());
}
It's easy to modify in both cases:
New functions require to be added to the proto static member method and that's all
Adding a new type is a matter of using it when call create, as shown in the above example
The functor will keep in charge of creating the N*M calls to be executed.
Moreover, you don't need to move your functions in a bunch of structs to be able to use them.
Related
I don't have a lot of experience with templates but I am wondering if the following scenario is possible. Assume we have a class S with static member stat. I can get it to dynamically generate different code using typeid as:
template <class S>
void foo()
{
if (typeid(S::stat) == typeid(AType))
implementation 1;
else
implementation 2;
}
But since all information is known at compile time is it possible to create a specialization of foo for S::stat being of type Atype?
You're probably looking to do something like this:
template<typename T> class foo_impl {
public:
static void foo()
{
// This is your implementation 2
}
};
template<> class foo_impl<AType> {
public:
static void foo()
{
// This is your implementation 1
}
};
template <class S>
void foo()
{
foo_impl<typename S::Stat>::foo();
}
One common way of solving this problem is through tag dispatching. We can, at compile time, produce different types for whether or not S::stat matches AType - and use those types to call different overloads:
template <class S>
void foo() {
foo_impl(std::is_same<decltype(S::stat), AType>{});
}
void foo_impl(std::true_type /* S::stat matches AType */) {
// implementation 1
}
void foo_impl(std::false_type /* S::stat doesn't match AType */) {
// implementation 2
}
I was not able to utilize the decltype solution because my compiler does not support it.
I was able to utilize the foo_impl class solution but only when I declare MyClass as:
class MyClass {
public:
typedef AType Stat;
static const Stat stat = VAL;
...
}
The question:
Is there a way to call the "base" template function from a specialized template function in C++, the way a child class can access the parent's versions of virtual methods when overriding them? (NOTE: I suspect the answer is "no" but would love to be wrong)
The context:
I often find myself specializing a template function only because a special case needs extra pre- or post-processing, not because the "guts" of the code have changed.
To give a contrived example:
With inheritance, you can do the following:
struct base {
virtual void go() { printf("%p", this); }
};
struct foo : base {
virtual void go() { printf("this foo lives at "); base::go(); }
};
... and calling foo::go() will print "this foo lives at <address>"
With templates, though:
template <typename T>
void go(T const &t) { printf("%p\n", &t); }
template <>
void go(foo const &f) {
printf("this foo lives at ");
??? how to access "base" template ???
}
You can work around the problem in an ugly way by factoring out a mess of little helper functions and specializing them instead of the function you actually care about:
template <typename T>
void _go_pre(T const &t) { /* do nothing */ }
template <typename T>
void _go_post(T const &t) { /* do nothing */ }
template <typename T>
void go(T const &t) {
_go_pre(t); /* just in case */
printf("%p\n", &t);
_go_post(t);
}
template<>
void _go_pre(foo const &t) { printf("this foo lives at "); }
... but that clutters the code significantly because now the "base" template needs to anticipate all the ways a "child" specialization might override it, and most types will use few, if any, of those hooks. The clutter becomes unreadable and unmaintainable pretty quickly, because the reason for these hooks is not known at the point where they are defined, and you have to test the different combinations of used/unused hooks.
All this is exactly like the problems you'd have with virtual method overrides in a world where a child class couldn't access original version provided by the parent class.
It's not possible directly. However, you can do with fewer (and IMO less ugly) helpers like this:
template <typename T>
void base_go(T const &t) { printf("%p\n", &t); }
template <typename T>
void go(T const &t) { base_go(t); }
template<>
void go(foo const &t) { printf("this foo lives at "); base_go(t); }
As an alternative, you could put the base_ variants into a separate namespace instead of giving them modified names.
If your foo is a normal type you can simple create a (non-template) function overload and call the templated version inside:
#include <iostream>
struct A {};
template<class T>
void f(T const&) {
std::cout << "in f<T>(T const&)" << std::endl;
}
void f(A const& a) {
std::cout << "in f(A const&)" << std::endl;
f<A>(a);
}
int main() {
A a;
f(a);
return 0;
}
I have a template class, say:
template<class T>
class someClient
{
void someCallbackA() {foo_->onA();}
void someCallbackB() {foo_->onB();}
private:
T* foo_;
};
which I can instantiate with a bunch of different types T which support the onA and onB interface. I happen to have a case where two out of the several different types T I use needs a particular behavior controlled from someClient so I need to add some function doBar() to these two types (call them Edge1 and Edge2). Then I want a part of the someClient code to call foo_->doBar() but without breaking when the type of foo_ does not have that. Is there a way to use boost::enable_if to have a someClient::doBar() which will call foo_->doBar() only for those two types, but not be there, or expand to nothing if the types are not Edge1 or Edge2?
I was thinking along the lines of:
template <class T, enable_if<mpl_or<is_same<T,Edge1>, is_same<T,Edge2> > >
someClient<T>::doBar() {foo_->doBar();}
You don't need to pull any special tricks at all if you just don't call member functions that don't make sense. Template member functions are only specialized when needed (unless you add an explicit specialization). So the following code works fine:
template <typename T> struct Foo
{
void do_foo() { p->foo(); }
void do_bar() { p->bar(); }
T * p;
};
struct A { void foo() {} };
int main()
{
A a;
Foo<A> x = { &a };
x.do_foo();
}
The fact that Foo<A>::do_bar wouldn't compile is not an issue, since the member function is never instantiated. And p->bar isn't a compiler error, because p has a dependent type and the line is thus only parsed in the second lookup phase (which never happens).
I think this does what you want. I used C++11 <type_traits> instead of boost's:
struct Edge {
void doBar() { std::cout << "did Bar."; }
};
template<typename T>
class someClient
{
public:
template<typename U = T>
typename
std::enable_if<std::is_same<U, Edge>::value, void>::type
doBar() { foo_->doBar(); }
template<typename U = T>
void doBar( typename std::enable_if<!std::is_same<U, Edge>::value, void>::type* = 0 )
{ /* do nothing */ }
private:
T* foo_;
};
int main()
{
someClient<int> i;
someClient<Edge> e;
i.doBar();
e.doBar(); // outputs "did Bar."
}
doBar() needs to be template itself for this to work, explanation here: std::enable_if to conditionally compile a member function
I seem to be unable to use multiple layers of templates in the following manner,
template <typename T>
template <T value>
void printValueAsInteger()
{
printf("value as integer is %i\n", (int) value);
}
so that it could be called as:
printValueAsInteger<123>();
It results in the following error message: too many template-parameter-lists.
It works if I use template <typename T, T value> with printValueAsInteger<int, 123>(), but that requires me to explicitly specify the type. How can I make it so that printValueAsInteger<123>() prints value as integer is 123?
edit:
I'll be more specific in what I need this for. My goal is to pass a member function as a function pointer, and I thought of wrapping it using templates:
template <typename T>
template <T* instance, void (T::*method)()>
void wrappedMethod()
{
(instance->*method)();
}
void callFunction(void (*function)())
{
(*function)();
}
and then pass it like this:
Base *instance = new Derived;
callFunction(&wrappedFunction<instance, Base::method>);
edit:
Err, I just realised that I probably shouldn't (and can't) use a runtime-defined variable as a template argument. I'm now trying to work around it using a class instantiated with the otherwise template arguments and creating a template function which uses that class. Or something like that. Nope, doesn't work.
Note that I cannot change the signature of callFunction, as it's part of a third party API.
At last!
I put the following in a header,
class Callable
{
public:
virtual ~Callable() { }
virtual void call() { }
};
typedef void (*functionPtr)();
extern unsigned nextMethodId;
extern functionPtr wrappedMethods[];
extern Callable *boundMethods[];
template <unsigned I>
class MethodWrapper
{
public:
static void function();
};
template <typename T>
class Method : public Callable
{
public:
Method(T* instance, void (T::*method)());
virtual void call();
private:
T* instance;
void (T::*method)();
};
template <typename T>
Method<T>::Method(T* instance, void (T::*method)())
: instance(instance), method(method) {
}
template <typename T>
void Method<T>::call()
{
if (instance && method)
(instance->*method)();
}
template <typename T>
static functionPtr bindMethod(T* instance, void (T::*method)())
{
boundMethods[nextMethodId] = new Method<T>(instance, method);
return (void (*)()) wrappedMethods[nextMethodId++];
}
and this in a source file:
#include "<insert header name here>.h"
unsigned nextMethodId = 0;
functionPtr wrappedMethods[] = {
&MethodWrapper<0>::function,
&MethodWrapper<1>::function,
&MethodWrapper<2>::function
};
Callable *boundMethods[sizeof(wrappedMethods) / sizeof(functionPtr)];
template <unsigned I>
void MethodWrapper<I>::function()
{
boundMethods[I]->call();
}
and I could use it like this:
Base *instance = new Derived;
void (*function)() = bindMethod(instance, &Base::method);
callFunction(function);
It successfully calls the derived instance's version of the method. Sadly, the amount of methods you are allowed to bind is fixed (three in this example), but it's easily extendable.
A simple transform is having the runtime value be an argument to the constructor of a functor that holds the instance pointer and the pointer to member function. The syntax at the place of use will change from:
Base *instance = new Derived;
callFunction(&wrappedFunction<instance, Base::method>);
To:
callFunction( WrappedFunction<Base,&Base::method>( instance ) );
The implementation of the WrappedFunction type is actually simple, so I leave it as an exercise. Note that a major change in this approach is that the argument to callFunction becomes a functor, and not a function pointer.
In C++11 (or with boost) the simplest way would be not coding anything and just use the available resources. Change the signature of callFunction to:
void callFunction( function<void ()> f );
And use bind to place the call:
callFunction( bind( &Base::method, instance ) );
For your first example, you can specify int as the type of template parameter:
template <int I>
void printValueAsInteger()
{
printf("value as integer is %i\n", I);
}
For your edit, you cannot use runtime-defined variables as you have already mentioned because templates are used at compile-time. Using std::bind and std::function would make it simple:
void callFunction(std::function<void()> f)
{
f();
}
Base *instance = new Derived;
callFunction(std::bind(&Base::method, instance));
After Comment
The only way I can think of is to make your member function static:
callFunction(&Base::method); // Okay if the method is declared static
Or use a global wrapper function with a global instance:
Base *instance = new Derived; // Global
void wrapperFunction()
{
instance->method();
}
callFunction(wrapperFunction);
I have a template member function in a class that is called for all bool, double, int and string. I want to carry out few instructions that are common to all the above mentioned data types. But for String last few lines of code is different. So can any one suggest me a better way to carry out this in a same template function.
template< class T>
xyz (t* a)
{
//few lines are common for all types for data
//last 3 lines of code is different for Strings
}
The solution, as often, is to factorize the common behavior and provide a mean to specialize some parts of the algorithm (see the Template Method pattern).
Here, you can do this quite easily by moving the last lines of your function in a function of its own, which can be specialized for certain data types. Remember that when it comes to functions, overloading should be preferred to template specialization.
template <class T>
void xyz(T * a)
{
//few lines are common for all types for data
xyz_finish(a);
}
template <class T>
void xyz_finish(T * a)
{
// default case (can be empty)
}
void xyz_finish(std::string * s)
{
// string case
}
Of course, your function should have a more descriptive name than the one I used...
You can also do the symmetrical operation: move the common behavior in a function, and overloads the "top-level" function:
template <class T>
void xyz(T * a)
{
common_behavior(a);
}
void xyz(std::string * s)
{
common_behavior(s);
// code specific to strings
}
template <class T>
void common_behavior(T * a)
{
//few lines that are common for all types for data
}
If you do not want or cannot create other functions, you can test the type of the parameter:
template <class T>
void xyz(T * a)
{
// common code
if (is_same<T, std::string>::value)
{
//code for strings
}
}
is_same is a class template containing a value which is true if its two parameters are the same type, available in TR1, Boost and C++0x. This solution will work only if the code in the if clause is valid for every data types you instantiate the template with. For example, if you use a member function of string in the if block, compilation will fail when instantiating the function with the other data types, since you cannot invoke a method on a primitive type.
You can move last 3 lines into some function, and use C++ function overloading, i.e. one for bool, second for int etc, i think.
struct Foo {
template <typename T>
voud foo (T *) {
foo ();
}
void foo (string *) {
foo ();
bar ();
}
private:
void foo () {
}
};
Or
struct Foo {
template <typename T>
void foo (T * t) {
do_foo (t);
}
void foo (string * s) {
do_foo (s);
bar (s);
}
private:
template <typename T>
void do_foo (T *) {
}
};
You could explicitly specialise Foo::foo outside the class.
tempalte <> void Foo :: foo (string *) {}
This seems like it could be put to devious use, though...
You only need to specialise your template for string, as follows:
template<> xyz(string* a) { /* code here, including modified lines */ }
EDIT: Apparently, I did not notice the "member function" bit of it. The solution would be to add an extra indirection, a function that you specialise for string and call at the end of your current function.