How to alias a template function inside a template class - c++

I have a need to implement 2 functions inside a templated class, where both functions do similar things, but not everything is the same. My proposed solution was to use if constexpr on a single template function, and then have an alias for each function:
template <typename T>
class MyClass
{
private:
template <bool test>
void TestFunc()
{
if constexpr(test)
{
// Do something
}
else
{
// Do other stuff
}
}
public:
?????? TestTrue = TestFunc<true>;
?????? TestFalse = TestFunc<false>;
}
I'm trying to figure out what should go where the question marks are, so far using, auto and const auto have not worked. I want the user to be able to call TestTrue() and TestFalse() directly from an object of the class directly.

You could do:
void TestTrue() { TestFunc<true>(); }
void TestFalse() { TestFunc<false>(); }
I don't think there's a better way.

For completeness, here's the ugly way.
As mentioned in the comments, TestFunc is a member function, not a type, so if you want to reference an explicit specialization of it, you'll need to use a member function pointer. In our case, these will be pointers of the following type.
using MemberTestFunction = void (MyClass::*)();
We can then acquire pointers to the true and false specialization of TestFunc like so:
template <typename T>
class MyClass
{
// ...
constexpr static MemberTestFunction TestTrue = &MyClass::TestFunc<true>;
constexpr static MemberTestFunction TestFalse = &MyClass::TestFunc<false>;
};
If you're not familiar with pointers to member functions, the syntax for calling TestTrue and TestFalse may look rather bizarre. If you're inside a member function, you can invoke these functions either by using the ->* operator, or by using std::invoke (C++17) from <functional>:
template <typename T>
class MyClass
{
// ...
void foo() {
// Direct call with pointer.
(this->*TestTrue)();
// Call using std::invoke.
std::invoke(TestTrue, this);
}
};
Alternatively, outside of MyClass, these calls would look like the following.
MyClass<nullptr_t> x;
// Using type deducation.
(x.*decltype(x)::TestTrue)();
// Using fully qualified name.
(x.*MyClass<nullptr_t>::TestTrue)();
// Using std::invoke (with type deducation).
std::invoke(decltype(x)::TestTrue, x);
It goes without saying this this is a needlessly obscure way of accomplishing any otherwise simple task. I would not advocate using this technique over creating new functions (as HolyBlackCat suggested) or simply naming TestFunc<true>() and TestFunc<false>() explicitly at the call site.

Transform function TestFunc to functor:
#include <iostream>
template <typename T>
class MyClass
{
private:
template <bool test>
struct TestFunc
{
void operator()() {
if constexpr(test)
{
std::cout << "TestTrue\n";
}
else
{
std::cout << "TestFalse\n";
}
}
};
public:
TestFunc<true> TestTrue;
TestFunc<false> TestFalse;
};
int main()
{
MyClass<int> myClass;
myClass.TestTrue();
myClass.TestFalse();
}

Related

How to declare the template argument for an overloaded function

I have a fairly big project that, regarding this question,
I can summarize with
this structure:
void do_something()
{
//...
}
template<typename F> void use_funct(F funct)
{
// ...
funct();
}
int main()
{
// ...
use_funct(do_something);
}
All is working ok until someone (me) decides to reformat a little
minimizing some functions, rewriting
as this minimum reproducible example:
void do_something(const int a, const int b)
{
//...
}
void do_something()
{
//...
do_something(1,2);
}
template<typename F> void use_funct(F funct)
{
// ...
funct();
}
int main()
{
// ...
use_funct(do_something);
}
And now the code doesn't compile with
error: no matching function for call
where use_funct is instantiated.
Since the error message was not so clear to me
and the changes were a lot I wasted a considerable
amount of time to understand that the compiler
couldn't deduce the template parameter
because do_something could now refer to
any of the overloaded functions.
I removed the ambiguity changing the function name,
but I wonder if there's the possibility to avoid
this error in the future not relying on template
argument deduction.
How could I specify in this case the template argument for do_something(), possibly without referring to a function pointer?
I haven't the slightest idea to express explicitly:
use_funct<-the-one-with-no-arguments->(do_something);
You can wrap the function in a lambda, or pass a function pointer after casting it to the type of the overload you want to call or explicitly specify the template parameter:
use_funct([](){ do_something (); });
use_funct(static_cast<void(*)()>(do_something));
use_funct<void()>(do_something);
Wrapping it in a lambda has the advantage, that it is possible to defer overload resolution to use_func. For example:
void do_something(int) {}
void do_something(double) {}
template<typename F> void use_funct(F funct) {
funct(1); // calls do_something(int)
funct(1.0); // calls do_something(double)
}
int main() {
use_funct([](auto x){ do_something (x); });
}
[...] possibly without referring to a function pointer?
I am not sure what you mean or why you want to avoid that. void() is the type of the function, not a function pointer. If you care about spelling out the type, you can use an alias:
using func_type = void();
use_funct<func_type>(do_something);

Call function with same name as method

I'm trying to define a template class that has some operations on a type.
The method ToString should be implemented to call the ToString in the namespace of whatever type the Tools template class has been instantiated with.
namespace X
{
class SomeType
{
};
std::wstring ToString(SomeType)
{
// ...
}
}
template<class T>
class Tools
{
static auto ToString(T& t)
{
return ToString(t);
}
}
I get an error in the Tools implementation of ToString. The compiler tries to recursively call the method ToString again instead of calling the ToString in namespace X.
I can't use X::ToString as that will fail when I try to instantiate the Tools class with a type from namespace Y. Eg, if I use:
namespace Y
{
class SomeOtherType
{
};
std::wstring ToString(SomeOtherType)
{
// ...
}
}
Y::SomeOtherType someOtherType;
auto s = Tools<Y::SomeOtherType>::ToString(someOtherType); // Would fail as SomeOtherType isn't in namespace X.
Is it possible to make this work?
I'm using VS 2015 Update 3. A solutions that work for that is preferred.
Related: calling a global function with a class method with the same declaration
Ok, I might have a solution. Add an intermediate function that is outside the class with a different name, that then calls with the correct name.
Add
namespace ImplementationDetail
{
template< class T >
auto ToStringHelper(T& t)
{
return ToString(t);
}
}
template<class T>
class Tools
{
auto ToString(T& t)
{
return ImplementationDetail::ToStringHelper(t);
}
}
Explicitly use
return ::X::ToString(t);
to reference the function in the X namespace, irrespective of which namespace the reference comes from.

Uses of pointers non-type template parameters?

Has anyone ever used pointers/references/pointer-to-member (non-type) template parameters?
I'm not aware of any (sane/real-world) scenario in which that C++ feature should be used as a best-practice.
Demonstation of the feature (for pointers):
template <int* Pointer> struct SomeStruct {};
int someGlobal = 5;
SomeStruct<&someGlobal> someStruct; // legal c++ code, what's the use?
Any enlightenment will be much appreciated!
Pointer-to-function:
Pointer-to-member-function and pointer-to-function non-type parameters are really useful for some delegates. It allows you to make really fast delegates.
Ex:
#include <iostream>
struct CallIntDelegate
{
virtual void operator()(int i) const = 0;
};
template<typename O, void (O::*func)(int)>
struct IntCaller : public CallIntDelegate
{
IntCaller(O* obj) : object(obj) {}
void operator()(int i) const
{
// This line can easily optimized by the compiler
// in object->func(i) (= normal function call, not pointer-to-member call)
// Pointer-to-member calls are slower than regular function calls
(object->*func)(i);
}
private:
O* object;
};
void set(const CallIntDelegate& setValue)
{
setValue(42);
}
class test
{
public:
void printAnswer(int i)
{
std::cout << "The answer is " << 2 * i << "\n";
}
};
int main()
{
test obj;
set(IntCaller<test,&test::printAnswer>(&obj));
}
Live example here.
Pointer-to-data:
You can use such non-type parameters to extend the visibility of a variable.
For example, if you were coding a reflexion library (which might very useful for scripting), using a macro to let the user declare his classes for the library, you might want to store all data in a complex structure (which may change over time), and want some handle to use it.
Example:
#include <iostream>
#include <memory>
struct complex_struct
{
void (*doSmth)();
};
struct complex_struct_handle
{
// functions
virtual void doSmth() = 0;
};
template<complex_struct* S>
struct csh_imp : public complex_struct_handle
{
// implement function using S
void doSmth()
{
// Optimization: simple pointer-to-member call,
// instead of:
// retrieve pointer-to-member, then call it.
// And I think it can even be more optimized by the compiler.
S->doSmth();
}
};
class test
{
public:
/* This function is generated by some macros
The static variable is not made at class scope
because the initialization of static class variables
have to be done at namespace scope.
IE:
class blah
{
SOME_MACRO(params)
};
instead of:
class blah
{
SOME_MACRO1(params)
};
SOME_MACRO2(blah,other_params);
The pointer-to-data template parameter allows the variable
to be used outside of the function.
*/
std::auto_ptr<complex_struct_handle> getHandle() const
{
static complex_struct myStruct = { &test::print };
return std::auto_ptr<complex_struct_handle>(new csh_imp<&myStruct>());
}
static void print()
{
std::cout << "print 42!\n";
}
};
int main()
{
test obj;
obj.getHandle()->doSmth();
}
Sorry for the auto_ptr, shared_ptr is available neither on Codepad nor Ideone.
Live example.
The case for a pointer to member is substantially different from pointers to data or references.
Pointer to members as template parameters can be useful if you want to specify a member function to call (or a data member to access) but you don't want to put the objects in a specific hierarchy (otherwise a virtual method is normally enough).
For example:
#include <stdio.h>
struct Button
{
virtual ~Button() {}
virtual void click() = 0;
};
template<class Receiver, void (Receiver::*action)()>
struct GuiButton : Button
{
Receiver *receiver;
GuiButton(Receiver *receiver) : receiver(receiver) { }
void click() { (receiver->*action)(); }
};
// Note that Foo knows nothing about the gui library
struct Foo
{
void Action1() { puts("Action 1\n"); }
};
int main()
{
Foo foo;
Button *btn = new GuiButton<Foo, &Foo::Action1>(&foo);
btn->click();
return 0;
}
Pointers or references to global objects can be useful if you don't want to pay an extra runtime price for the access because the template instantiation will access the specified object using a constant (load-time resolved) address and not an indirect access like it would happen using a regular pointer or reference.
The price to pay is however a new template instantiation for each object and indeed it's hard to think to a real world case in which this could be useful.
The Performance TR has a few example where non-type templates are used to abstract how the hardware is accessed (the hardware stuff starts at page 90; uses of pointers as template arguments are, e.g., on page 113). For example, memory mapped I/O registered would use a fixed pointer to the hardware area. Although I haven't ever used it myself (I only showed Jan Kristofferson how to do it) I'm pretty sure that it is used for development of some embedded devices.
It is common to use pointer template arguments to leverage SFINAE. This is especially useful if you have two similar overloads which you couldn't use std::enable_if default arguments for, as they would cause a redefinition error.
This code would cause a redefinition error:
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
void foo (T x)
{
cout << "integral";
}
template <typename T, typename = std::enable_if_t<std::is_floating_point<T>::value>>
void foo (T x)
{
cout << "floating";
}
But this code, which utilises the fact that valid std::enable_if_t constructs collapse to void by default, is fine:
// This will become void* = nullptr
template <typename T, std::enable_if_t<std::is_integral<T>::value>* = nullptr>
void foo (T x)
{
cout << "integral";
}
template <typename T, std::enable_if_t<std::is_floating_point<T>::value>* = nullptr>
void foo (T x)
{
cout << "floating";
}
Occasionally you need to supply a callback function having a particular signature as a function pointer (e.g. void (*)(int)), but the function you want to supply takes different (though compatible) parameters (e.g. double my_callback(double x)), so you can't pass its address directly. In addition, you might want to do some work before and after calling the function.
It's easy enough to write a class template that tucks away the function pointer and then calls it from inside its operator()() or some other member function, but this doesn't provide a way to extract a regular function pointer, since the entity being called still requires the this pointer to find the callback function.
You can solve this problem in an elegant and typesafe way by building an adaptor that, given an input function, produces a customised static member function (which, like a regular function and unlike a non-static member function, can have its address taken and used for a function pointer). A function-pointer template parameter is needed to embed knowledge of the callback function into the static member function. The technique is demonstrated here.

Universal function pointer

There is some class which have methods like:
int getSomething1();
std::string getSomething2();
someClass getSomething3();
There is structure which describes fields of this class like:
{"name of field", pointer to getter, std::type_info}
Then I would like to use it as follows:
if(type == int){
field_int = (int)getter();
}
else if(type == std::string){
field_string = (std::string)getter();
}
etc.
How to transform getters like
int getSomething1();
std::string getSomething2();
etc.
to some universal function pointer and then to get the correct value of field?
This answer of mine to another question addresses your problem pretty well. With some minor modifications, you get this:
template<class C, class T>
T get_attribute(const C& instance, T (C::*func)() const) {
return (instance.*func)();
}
Assuming the following:
struct Foo {
int getSomething1() const;
std::string getSomething2() const;
someClass getSomething3() const;
};
You can use it like this:
Foo foo;
int value = get_attribute<Foo, int>(foo, &Foo::getSomething1);
std::string value = get_attribute<Foo, std::string>(foo, &Foo::getSomething2);
someClass value = get_attribute<Foo, someClass>(foo, &Foo::getSomething3);
You can of course transform get_attribute to a functor to bind some or all of the arguments.
There is no formal universal function pointer, the equivalent of void*
for data. The usual solution is to use void (*)(); you are guaranteed
that you can convert any (non-member) function pointer to this (or any
other function pointer type) and back without loss of information.
If there is a certain similarity in the function signatures (e.g. all
are getters, with no arguments) and how they are used, it may be
possible to handle this with an abstract base class and a set of derived
classes (possibly templated); putting pointers to instances of these
classes in a map would definitely be more elegant than an enormous
switch.
What you are trying to achieve can be better achieved with already existing containers such as a boost fusion sequence. I'd advice that you try this first.
Templates to the rescue!
// Create mapping of type to specific function
template <typename T> T getSomething(); // No default implementation
template <> int getSomething<int>() { return getSomething1(); }
template <> std::string getSomething<std::string>() { return getSomething2(); }
template <> someClass getSomething<someClass>() { return getSomething3(); }
// Convenience wrapper
template <typename T> void getSomething(T& t) { t = getSomething<T>(); }
// Use
int i = getSomething<int>();
std::string s;
getSomething(s);
As I understand, your difficulty is in storing the function pointers, since they are of different types. You can solve this using Boost.Any and Boost.Function.
#include <boost/any.hpp>
#include <boost/function.hpp>
int getInt() {
return 0;
}
std::string getString() {
return "hello";
}
int main()
{
boost::function<boost::any ()> intFunc(getInt);
boost::function<boost::any ()> strFunc(getString);
int i = boost::any_cast<int>(intFunc());
std::string str = boost::any_cast<std::string>(strFunc());
}

Template type deduction with a non-copyable class

Suppose I have an autolocker class which looks something like this:
template <T>
class autolocker {
public:
autolocker(T *l) : lock(l) {
lock->lock();
}
~autolocker() {
lock->unlock();
}
private:
autolocker(const autolocker&);
autolocker& operator=(const autolocker&);
private:
T *lock;
};
Obviously the goal is to be able to use this autolocker with anything that has a lock/unlock method without resorting to virtual functions.
Currently, it's simple enough to use like this:
autolocker<some_lock_t> lock(&my_lock); // my_lock is of type "some_lock_t"
but it is illegal to do:
autolocker lock(&my_lock); // this would be ideal
Is there anyway to get template type deduction to play nice with this (keep in my autolocker is non-copyable). Or is it just easiest to just specify the type?
Yes you can use the scope-guard technique
struct autolocker_base {
autolocker_base() { }
protected:
// ensure users can't copy-as it
autolocker_base(autolocker_base const&)
{ }
autolocker_base &operator=(autolocker_base const&)
{ return *this; }
};
template <T>
class autolocker : public autolocker_base {
public:
autolocker(T *l) : lock(l) {
lock->lock();
}
autolocker(const autolocker& o)
:autolocker_base(o), lock(o.lock)
{ o.lock = 0; }
~autolocker() {
if(lock)
lock->unlock();
}
private:
autolocker& operator=(const autolocker&);
private:
mutable T *lock;
};
Then write a function creating the autolocker
template<typename T>
autolocker<T> makelocker(T *l) {
return autolocker<T>(l);
}
typedef autolocker_base const& autolocker_t;
You can then write it like this:
autolocker_t lock = makelocker(&my_lock);
Once the const reference goes out of scope, the destructor is called. It doesn't need to be virtual. At least GCC optimizes this quite well.
Sadly, this means you have to make your locker-object copyable since you need to return it from the maker function. But the old object won't try to unlock twice, because its pointer is set to 0 when it's copied, so it's safe.
Obviously you can't get away with autolocker being a template, because you want to use it as a type, and templates must be instantiated in order to obtain types.
But type-erasure might be used to do what you want. You turn the class template into a class and its constructor into a member template. But then you'd have to dynamically allocate an inner implementation object.
Better, store a pointer to a function that performs the unlock and let that function be an instance of a template chosen by the templatized constructor. Something along these lines:
// Comeau compiles this, but I haven't tested it.
class autolocker {
public:
template< typename T >
autolocker(T *l) : lock_(l), unlock_(&unlock<T>) { l->lock(); }
~autolocker() { unlock_(lock_); }
private:
autolocker(const autolocker&);
autolocker& operator=(const autolocker&);
private:
typedef void (*unlocker_func_)(void*);
void *lock_;
unlocker_func_ unlock_;
template <typename T>
static void unlock(void* lock) { ((T*)lock)->unlock(); }
};
I haven't actually tried this and the syntax might be wrong (I'm not sure how to take the address of a specific function template instance), but I think this should be doable in principle. Maybe someone comes along and fixes what I got wrong.
I like this a lot more than the scope guard, which, for some reason, I never really liked at all.
I think jwismar is correct and what you want is not possible with C++. However, a similar (not direct analogue) construct is possible with C++0x, using several new features (rvalues/moving and auto variable type):
#include <iostream>
template <typename T>
class autolocker_impl
{
public:
autolocker_impl(T *l) : lock(l) {
lock->lock();
}
autolocker_impl (autolocker_impl&& that)
: lock (that.lock)
{
that.lock = 0;
}
~autolocker_impl() {
if (lock)
lock->unlock();
}
private:
autolocker_impl(const autolocker_impl&);
autolocker_impl& operator=(const autolocker_impl&);
private:
T *lock;
};
template <typename T>
autolocker_impl <T>
autolocker (T* lock)
{
return autolocker_impl <T> (lock);
}
struct lock_type
{
void lock ()
{ std::cout << "locked\n"; }
void unlock ()
{ std::cout << "unlocked\n"; }
};
int
main ()
{
lock_type l;
auto x = autolocker (&l);
}
autolocker is a class template, not a class. Your "this would be ideal" is showing something that doesn't make sense in C++.