I have a question somewhat similar to this one, but for a more limited case which I believe should be possible somehow: I want to construct a static constexpr array of function calls from a number of lambdas, each sharing the same signature. The static and constexpr part is important here since I'm on an embedded system, where I want to make sure such tables end up in Flash.
So basically what I want to do is
#include<vector>
#include<functional>
#include<variant>
using params_t = std::vector<std::variant<int, float /*maybe others*/ >>;
struct command_t {
using callable_t = std::function<void(params_t)>;
const callable_t func;
//other members..
};
class AClass {
template<typename func_t>
constexpr static command_t::callable_t make_callable(func_t fun) {
return [fun](params_t params){/*construct a call to fun using params and template magic*/};
}
static void mycommand();
static void mycommand2(int i);
//The following fails:
///"error: in-class initialization of static data member 'const command_t AClass::commands [2]' of non-literal type"
static constexpr command_t commands[2] = {command_t{make_callable(mycommand)},
command_t{make_callable(mycommand2)}};
};
On coliru
Note that the type erasure here is quite limited, since the signature of the lambda varies only by the signature of the capture of fun. The function call obviously doesn't (and cannot) need to be constexpr, only the construction.
So basically my question is can I somehow make the commands array static constexpr, either somehow using std::function, or something like inplace_function, or perhaps by spinning my own code for type-erasing the lambda in this specific case?
In general, this is not possible since the capture of a lambda can get arbitrary large and hence, at some point we need a heap allocation which then kills any hopes of constexpr pre-C++20 (and I don't think C++20 will help much for this case, either).
But you only want to capture a function pointer if I see this right and that we can do:
#include <vector>
#include<variant>
using params_t = std::vector<std::variant<int, float /*maybe others*/ >>;
struct command_t {
using callable_t = void (*)(std::vector<params_t>);
const callable_t func;
//other members..
};
template<auto f>
void wrap(std::vector<params_t>){
// make this dependent of f, maybe use function_traits for fancy stuff
}
class AClass {
static void mycommand();
static void mycommand2(int i);
static constexpr command_t commands[2] = {wrap<mycommand>, wrap<mycommand2>};
};
int main() {
}
Thanks to xskxzr for valuable suggestions.
Since mycommanN have different signatures and you need to capture them, I don't see a way to have a constexpr vector. Maybe someone can come up with a better design.
I have a solution: use std::tuple. But I don't really like as it is really cumbersome to work with tuple as a container. For instance iterating over it is ... let's say not a walk in the park. Anyway, here it is in case it does help:
using params_t = std::vector<std::variant<int, float /*maybe others*/>>;
// I needed to lift this out of AClass because of ... complicated reasons
// (short version: when both are AClass members
// the return type of `make_command` is not resolved in the init of `commands`
// because both are static, `commands` is not a template and `make_command` is a template
// tbh I don't know exactly what is happening. It's one of those dark corners of C++)
template <class RealFunc>
static constexpr auto make_command(RealFunc real_func) {
return [real_func](params_t params) { /*magic*/ };
}
struct AClass {
static void mycommand();
static void mycommand2(int i);
static constexpr std::tuple commands{make_command(mycommand),
make_command(mycommand2)};
};
// usage
auto test() {
constexpr auto command0 = std::get<0>(AClass::commands<>);
params_t params0 = {};
return command0(command0);
}
Related
In the Objc source code, I found the following code. What is the meaning of this code and how to understand it?
objc/Project Headers/DenseMapExtras.h line:38
template <typename Type>
class ExplicitInit {
alignas(Type) uint8_t _storage[sizeof(Type)];
public:
template <typename... Ts>
void init(Ts &&... Args) {
new (_storage) Type(std::forward<Ts>(Args)...);
}
Type &get() {
return *reinterpret_cast<Type *>(_storage);
}
};
Below is my test code:
class MyC{
public:
long l1;
long l2;
MyC(long _l1, long _l2){
l1 = _l1;
l2 = _l2;
}
};
int main(){
MyExplicitInit<MyC> e1 {};
e1.init();
return 0;
}
The compiler prompts the following error:
In the Objc source code, I found the following code. What is the
meaning of this code and how to understand it?
To me it looks like a kind-of-factory which can be used as an alternative to the Construct On First Use Idiom. An instantiated class here represents a storage for an instance you can initialise and request when needed. As far as I understand it's not supposed to be used for local variables (it doesn't make much sense, despite being technically possible) and this is also suggested by the comments of code section with the said class template:
// We cannot use a C++ static initializer to initialize certain globals because
// libc calls us before our C++ initializers run. We also don't want a global
// pointer to some globals because of the extra indirection.
//
// ExplicitInit / LazyInit wrap doing it the hard way
For the error you are experiencing:
No matching operator new function for non-allocating placement new expression;
include <new>
Assuming that you just added that piece of code somewhere in your own sources, the problem here is that you didn't include the <new> header. As simple as that - the error just says that you need to add #include <new> since so-called placement new is not part of the "default" C++, it's an overloaded operator declared in this header.
Second, your init function expects arguments that matches one of the existing (non-aggregate) constructors of the given class, so you are expected to pass arguments which are either match the constructor parameters or can be implicitly converted to them: e1.init(1l, 2l)
A complete example looks something like this:
#include <_types/_uint8_t.h>
#include <new>
namespace objc {
template <typename Type>
class ExplicitInit {
alignas(Type) uint8_t _storage[sizeof(Type)];
public:
template <typename... Ts>
void init(Ts &&... Args) {
new (_storage) Type(std::forward<Ts>(Args)...);
}
Type &get() {
return *reinterpret_cast<Type *>(_storage);
}
};
};
struct sample_struct {
long l1, l2;
sample_struct(long _l1, long _l2): l1{_l1}, l2{_l2} {}
};
sample_struct& getInstance(bool should_init = false) {
static objc::ExplicitInit<sample_struct> factory;
if (should_init) {
factory.init(1l, 2l);
}
return factory.get();
}
I have a class that is trying to encapsulate the setup of an interrupt. I need to pass an instantiated reference/pointer/etc to an external function that then calls my function.
I can't change this function:
typedef void (*voidFuncPtr)(void);
void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode);
My Library:
class Buttons ...
bool Buttons::begin(int buttonPin)
{
//attachInterrupt(buttonPin, (this->*func)Buttons::released, HIGH);
attachInterrupt(buttonPin, &Buttons::released, LOW);
return 0;
}
void Buttons::released()
{
numButtonPresses++;
pressLength = millis()-pressStartTime;
pressStartTime = 0;
buttonState=LOW;
}
The problem is that I don't know what to put inside the attachInterupt function in the Buttons::begin method. I am sure I am doing something wrong in the way I am approaching this problem, but I am not sure what it is or what I should do about it. I would greatly appreciate any suggestions!
You're using an old c-style function pointer callback. This does not work for member function of an object. If you can't change the callback, you need to make the Buttons::released function static.
The problem you were facing is that you wanted to pass two pieces of data as your callback: the member function, and a class instance to call that member function on.
With the existing interface, which only accepts a function pointer with no arguments, you might create a static Button object and then write a static wrapper function that calls someStaticButton.released(). Then you could pass the address of this wrapper function as your callback. Justin Time’s answer approaches from a different, and clever, direction: wrap the instance and member in a singleton class, and give that a static member callback function. A simpler way to allow more than one singleton class would be to add a numeric ID as template parameter.
You might also be able to make button::released() a static member function, but your implementation appears to refer to member data. This wouldn’t be an option unless there is only one button in the program, represented by a singleton class.
If you can pass the instance pointer as the first argument to your callback function, or any other argument that can do a round-trip conversion to and from an object pointer (such as void* or any integer as wide as intptr_t), you can make the member function static and pass the this pointer as its argument.
If you can overload attachInterrupt to take a std::function object as your callback, you can do what you originally wanted. This type can represent a static function, a member function, or a closure containing a member function and a this pointer.
You unfortunately say you cannot change the callback function, but perhaps you can extend the interface in a backward-compatible way, such as:
#include <array>
#include <iostream>
#include <functional>
#include <stdint.h>
#include <stdlib.h>
#include <utility>
using std::cout;
using std::endl;
using voidFuncPtr = void(*)(void);
using Callback = std::function<void(void)>;
std::array<Callback, 1> interrupts;
void attachInterruptEx( const uint32_t pin,
Callback&& callback,
const uint32_t /* unused */ )
{
interrupts.at(pin) = std::move(callback);
}
void attachInterrupt( const uint32_t pin,
const voidFuncPtr callbackPtr,
const uint32_t mode )
{
/* Passing callbackPtr to a function that expects Callback&& implicitly
* invokes the constructor Callback(voidFuncPtr). This is sugar for
* std::function<void(void)>(void(*)(void)). That is, it initializes a
* temporary Callback object from callbackPtr.
*/
return attachInterruptEx( pin, callbackPtr, mode );
}
class Buttons {
public:
Buttons() = default;
bool begin(int buttonPin);
void released();
unsigned long buttonPresses() { return numButtonPresses; }
private:
// Empty stub function, probably calls a timer.
unsigned long millis() { return 0; };
static constexpr uint32_t LOW = 0;
uint32_t buttonState = LOW;
unsigned long numButtonPresses = 0;
unsigned long pressStartTime = 0;
unsigned long pressLength = 0;
};
/* Per C++17, a constant known at compile time is not odr-used, so this
* definition is deprecated. Still included out of an abundance of caution.
* It cannot have an initializer.
*/
constexpr uint32_t Buttons::LOW;
bool Buttons::begin(int buttonPin)
{
/* The C++17 Standard says little about the return type of std::bind().
* Since the result is a callable object, a std::function can be initialized
* from it. I make the constructor call explicit in case the return type of
* std::bind is a subclass of std::function in some implementation, and
* it resolves the overload in a way we don't expect.
*/
attachInterruptEx( static_cast<uint32_t>(buttonPin),
Callback(std::bind(&Buttons::released, this)),
LOW );
return false;
}
void Buttons::released()
{
numButtonPresses++;
pressLength = millis()-pressStartTime;
pressStartTime = 0;
buttonState=LOW;
}
int main(void)
{
Buttons buttons;
buttons.begin(0);
interrupts[0]();
// Should be 1.
cout << buttons.buttonPresses() << endl;
return EXIT_SUCCESS;
}
[Note that this code will use the following simplified version of your MCVE, primarily to have an easily-usable callback caller when testing & demonstrating the implementation:]
// Pointer type.
typedef void (*voidFuncPtr)(void);
// Dummy callback callers.
void takesVoidFuncPtr(voidFuncPtr vfp) {
std::cout << "Now calling vfp...\n";
vfp();
std::cout << "vfp called.\n";
}
struct DelayedCaller {
voidFuncPtr ptr;
DelayedCaller(voidFuncPtr p) : ptr(p) {}
void callIt() { return ptr(); }
};
// Simple stand-in for Button.
struct HasMemberFunction {
std::string name;
HasMemberFunction(std::string n) : name(std::move(n)) {}
void memfunc() { std::cout << "-->Inside " << name << ".memfunc()<--\n"; }
void funcmem() { static std::string out("Don't call me, I'm lazy. >.<\n"); std::cout << out; }
};
// Calling instance.
HasMemberFunction hmf("instance");
Ideally, you'd be able to bind the function to an instance with a lambda, and pass that to the consuming function as the callback. Unfortunately, though, capturing lambdas can't be converted to non-member function pointers, so this option isn't viable. However...
[Note that I have omitted proper encapsulation both for brevity, and for a demonstration of this approach's caveats at the end of the answer. I would recommend adding it if you actually use this.]
// Helper.
// Can easily be simplified if desired, Caller and MultiCaller only use FuncPtrTraits::ContainingClass.
namespace detail {
template<typename...> struct Pack {};
template<typename T> struct FuncPtrTraits;
template<typename Ret, typename Class, typename... Params>
struct FuncPtrTraits<Ret (Class::*)(Params...)> {
using ReturnType = Ret;
using ContainingClass = Class;
using ParameterList = Pack<Params...>;
};
template<typename T>
using ContainingClass = typename FuncPtrTraits<T>::ContainingClass;
} // detail
// Calling wrapper.
// Only allows one pointer-to-member-function to be wrapped per class.
template<typename MemFunc, typename Class = detail::ContainingClass<MemFunc>>
struct Caller {
static_assert(std::is_member_function_pointer<MemFunc>::value, "Must be built with pointer-to-member-function.");
static Class* c;
static MemFunc mf;
static void prep(Class& cls, MemFunc mem) { c = &cls; mf = mem; }
static void clean() { c = nullptr; mf = nullptr; }
static void call() { return (c->*mf)(); }
// Constructor is provided for convenience of creation, to effectively tie prep() to deduction guide.
// Note that it operates on static members only.
// Convenient, but likely confusing. ...Probably best not to do this. ;3
Caller(Class& cls, MemFunc mem) { prep(cls, mem); }
// Default constructor is required if we provide the above hax ctor.
Caller() = default;
};
template<typename MemFunc, typename Class> Class* Caller<MemFunc, Class>::c = nullptr;
template<typename MemFunc, typename Class> MemFunc Caller<MemFunc, Class>::mf = nullptr;
We can instead provide the desired behaviour by using a wrapper class, which stores the desired function and instance as static member variables, and provides a static member function that matches voidFuncPtr and contains the actual, desired function call. It can be used like so:
std::cout << "\nSimple caller, by type alias:\n";
using MyCaller = Caller<decltype(&HasMemberFunction::memfunc)>;
MyCaller::prep(hmf, &HasMemberFunction::memfunc);
takesVoidFuncPtr(&MyCaller::call);
MyCaller::clean(); // Not strictly necessary, but may be useful once the callback will no longer be called.
// Or...
std::cout << "\nSimple caller, via dummy instance:\n";
Caller<decltype(&HasMemberFunction::memfunc)> caller;
caller.prep(hmf, &HasMemberFunction::memfunc);
takesVoidFuncPtr(&caller.call);
caller.clean(); // Not strictly necessary, but may be useful once the callback will no longer be called.
That's a bit of a mess, so a hacky constructor is provided to simplify it.
[Note that this may violate the principle of least astonishment, and thus isn't necessarily the best option.]
std::cout << "\nSimple caller, via hax ctor:\n";
Caller clr(hmf, &HasMemberFunction::memfunc);
takesVoidFuncPtr(&clr.call);
clr.clean(); // Not strictly necessary, but may be useful once the callback will no longer be called.
Now, this version only allows one function to be wrapped per class. If multiple functions per class are required, we'll need to expand it a little.
[Note that this would be pretty awkward to typedef, as the optimal template parameter order places the first pointer-to-member-function first, to allow Class to be automatically deduced if only one function needs to be wrapped; the "hax ctor" approach was primarily intended for this version of Caller, although a deduction guide could likely also be used to swap Class and MemFunc.]
[Also note that all wrapped member functions must have the same signature.]
// Calling wrapper.
// Slightly more complex version, allows multiple instances of MemFunc to be wrapped.
template<typename MemFunc, typename Class = detail::ContainingClass<MemFunc>, typename... MemFuncs>
struct MultiCaller {
static_assert(std::is_member_function_pointer<MemFunc>::value, "Must be built with pointer-to-member-function.");
static_assert(std::conjunction_v<std::is_same<MemFunc, MemFuncs>...>, "All pointers-to-member-function must be the same type.");
static Class* c;
static std::array<MemFunc, 1 + sizeof...(MemFuncs)> mfs;
static void prep(Class& cls, MemFunc mem, MemFuncs... mems) { c = &cls; mfs = { mem, mems... }; }
static void clean() { c = nullptr; for (auto& m : mfs) { m = nullptr; } }
// Registered functions are wrapped by index, with index specified as a template parameter to match empty parameter list.
template<size_t N = 0, bool B = (N < mfs.size())>
static void call() {
static_assert(B, "Index must be a valid index for mfs.");
return (c->*mfs[N])();
}
// Constructor is provided for convenience of creation, to effectively tie prep() to deduction guide.
// Note that it operates on static members only.
// Convenient, but likely confusing. Primarily used because instantiation & preparation get really repetitive otherwise.
MultiCaller(Class& cls, MemFunc mem, MemFuncs... mems) { prep(cls, mem, mems...); }
// Default constructor is required if we provide the above hax ctor.
MultiCaller() = default;
};
template<typename MemFunc, typename Class, typename... MemFuncs> Class* MultiCaller<MemFunc, Class, MemFuncs...>::c = nullptr;
template<typename MemFunc, typename Class, typename... MemFuncs> std::array<MemFunc, 1 + sizeof...(MemFuncs)> MultiCaller<MemFunc, Class, MemFuncs...>::mfs = {nullptr};
It can be used by type alias as before, or the "hax ctor" can be used to couple it to a deduction guide like so:
std::cout << "\nMulti-registration caller, by type alias:\n";
using MyMultiCaller = MultiCaller<decltype(&HasMemberFunction::memfunc), HasMemberFunction, decltype(&HasMemberFunction::funcmem)>;
MyMultiCaller::prep(hmf, &HasMemberFunction::memfunc, &HasMemberFunction::funcmem);
takesVoidFuncPtr(&MyMultiCaller::call<0>); // memfunc
takesVoidFuncPtr(&MyMultiCaller::call<1>); // funcmem
MyMultiCaller::clean(); // Not strictly necessary, but may be useful once the callback will no longer be called.
// Or...
std::cout << "\nMulti-registration caller, via hax ctor:\n";
MultiCaller mclr(hmf, &HasMemberFunction::memfunc, &HasMemberFunction::funcmem);
takesVoidFuncPtr(&mclr.call<0>); // memfunc
takesVoidFuncPtr(&mclr.call<1>); // funcmem
mclr.clean(); // Not strictly necessary, but may be useful once the callback will no longer be called.
Note that in all cases, this has all the caveats of static members. In particular, since the binding relies on the static class members and isn't contained within the wrapper function itself, modifying the members after a callback is passed will immediately change the results of calling said already-passed callback.
std::cout << "\nBut alas:\n";
MyCaller::prep(hmf, &HasMemberFunction::memfunc);
DelayedCaller dc(&MyCaller::call);
dc.callIt(); // Output: "-->Inside instance.memfunc()<--"
std::cout << "Changing the registered instance will...\n";
HasMemberFunction hmf2("spinstance");
MyCaller::c = &hmf2;
dc.callIt(); // Output: "-->Inside spinstance.memfunc()<--"
You can see the different variants here, on Compiler Explorer.
Updates in bold
I am writing a hash function for a table of function pointers with the limitation that the structure of the function pointers and function table cannot be modified (i.e. they have been published to third-parties). Based on Can std::hash be used to hash function pointers?, std::hash can be used for function pointers. Adopting that, it yields the following solution.
The tedious part about this solution is that every time we add new APIs to FuncPointers struct, we'd have to modify the hash specialization to add the corresponding change (i.e. hashFunc(hashedValue, pFuncs->func3) ).
I am wondering if there's a better way to implement this hashing of function pointers so continuous modification to the hash specialization can be avoided?
typedef void (*func_type1) (int);
typedef void (*func_type2) (double);
typedef struct FuncPointers
{
func_type1 func1;
func_type2 func2;
...
} FuncPointers;
template <typename T> void hashFunc (size_t & HashedValue, T funcPointer)
{
std::hash<T> hash;
HashedValue ^= hash(funcPointer); // the XOR operator is randomly picked
}
namespace std
{
template<> struct hash<FuncPointers>
{
size_t operator()(FuncPointers *pFuncs)
{
size_t hashedValue = 0;
hashFunc(hashedValue, pFuncs->func1);
hashFunc(hashedValue, pFuncs->func2);
...
return hashedValue;
}
};
}
Start with this: https://stackoverflow.com/a/7115547/1774667
It provides a hash_tuple::hash<Tuple> that is a valid decent quality hasher (with combining and recursion support!) for a std::tuple.
Next, change FuncPointers as follows:
struct FuncPointers:std::tuple<func_type1, func_type2 /*, ...*/> {
// optional:
func_type1 func1() const { return std::get<0>(*this); }
func_type1& func1() { return std::get<0>(*this); }
//...
};
namespace std {
template<>
struct hash<FuncPointers> {
template<typename... Ts>
std::size_t operator()( std::tuple<Ts...> const& funcs ) const {
return hash_tuple::hash<std::tuple<Ts...>>{}(funcs);
}
};
}
which redirects your std::hash<FuncPointers> to invoke hash_tuple::hash<std::tuple<...>> on the parent of FuncPointers. If you do not want to inherit from std::tuple, changing it to a has-a instead of an is-a relationship should be easy.
The optional func() accessors give you closer to the old interface (just requires a () added), but also adds boilerplate.
An alternative would be:
template<unsigned N>
auto func() const->decltype( std::get<N>(*this) ){ return std::get<N>(*this); }
template<unsigned N>
auto& func()->decltype( std::get<N>(*this) ){ return std::get<N>(*this); }
which changes funcPointers.func1 to funcPointers.func<1>(), but gets rid of tonnes of boilerplate when you add a new func, and stays pretty similar to the old interface of funcPointers.
If there is not much code that is using the old interface, using std::get<N>() makes some sense.
If your names are more descriptive than func1 and you only used that for the example, an enumeration of the function names can be used with std::get or func<X> above. If you go with func<X> you can even make it typesafe (force the use of the named functions).
You'd be better off making your FuncPointers a std::tuple<func_type1, func_type2>. Then see this answer on hashing.
BTW, typedef struct FuncPointers { } FuncPointers is a C-ism which has never been necessary in C++.
My settings module has some redundant code:
#include <QSettings>
class MySettings
{
public:
// param1
void setParam1(QString param1) { _settings.setValue("param1", param1); }
string param1() { return _settings.value("param1").toString(); }
// param2
void setParam2(int param2) { _settings.setValue("param2", param2); }
int param2() { _settings.value("param2").toInt(); }
// param3
void setParam3(int param3) { _settings.setValue("param3", param3); }
int param3() { _settings.value("param3").toInt(); }
private:
QSettings _settings;
}
I managed to reduce the amount of code to write by using a macro. Here is an example for the QString parameter type:
#define INTSETTING(setter, getter) \
void set##setter(QString getter) { settings.setValue(#getter, getter);} \
QString getter() {return settings.value(#getter).toString();}
Since I'm using C++, I know that macro usage is bad. I'm looking for a cleaner alternative.
I gave a Qt example (QString) but it is a more general question.
Edit:
The macros make the definition of the above class much simpler:
class MySettings
{
public:
STRINGSETTING(Param1, param1)
INTSETTING(Param2, param2)
INTSETTING(Param3, param3)
STRINGSETTING(DefaultTitle, defaultTitle)
INTSETTING(MaxDocCount, maxDocCount)
private:
QSettings _settings;
}
You can either answer this in a religious fashion, or you can go back to the old principle: if it makes your code more readable, do it.
There are a lot of people who answer this in a religious way, they just hate the preprocessor and everything that's to do with it, and ban its use from their code.
On the other hand, there are people who routinely define macros to do repetitive task, I have done so on several occasions, most frequently just defining a macro for the use within a single function (used much in the way you can define subfunctions in GNU-C).
I think, the way people think about it is quite similar to the way people think about the goto statement: Most deamonize its use, others say it has its positive uses and should not be viewed as evil in itself. You need to decide this for yourself.
Here is one way that does not use macros:
class MySettings
{
public:
template <size_t N>
void setParam(QString param) { _settings.setValue(names[N], param); }
template <size_t N, typename T>
T param() { return _settings.value(names[N]).toString(); }
private:
QSettings _settings;
const char* names[3] = { "param1", "param2", "param3" };
}
You change the syntax a little so say e.g. settings.setParam<1>("string") and settings.param<1, string>() but in any case names param1, param2 etc were not so informative.
The only inconvenience is that the caller needs to specify the return type of param() apart from the parameter number. To get rid of this, you can specify all parameter types within MySettings, like this:
class MySettings
{
using types = std::tuple<string, int, int>;
public:
template<size_t N>
void setParam(QString param) { _settings.setValue(names[N], param); }
template<size_t N>
typename std::tuple_element<N, types>::type
param() { return _settings.value(names[N]).toString(); }
private:
QSettings _settings;
const char* names[3] = { "param1", "param2", "param3" };
}
You could of course further generalize this class to be used as a base for other settings classes. Within the base, the only things that need to be customized are members types and names.
However, keep in mind that if parameter names are informative indeed unlike your example, e.g. setTitle, setColor etc. then most probably there is no way to avoid macros. In this case, I prefer a macro that generates an entire struct rather than a piece of code within another class, hence probably polluting its scope. So there could be a struct for each individual parameter, generated by a macro given the parameter name. The settings class would then inherit all those individual structs.
EDIT
I "forgot" generalizing toString() in param() (thanks #Joker_vD). One way is this:
template<size_t N>
typename std::tuple_element<N, types>::type
param() {
using T = typename std::tuple_element<N, types>::type;
return get_value(type<T>(), _settings.value(names[N]));
}
where get_value<T>() is a helper function that you need to define and overload for the types supported by QSettings, calling the appropriate conversion member function for each type, for instance
template<typename V>
string get_value(type<string>, const V& val) { return val.toString(); }
template<typename V>
int get_value(type<int>, const V& val) { return val.toInt(); }
and type is just a helper struct:
template<typename T>
struct type { };
If QSettings itself was designed with templates in mind, you wouldn't need this. But you probably wouldn't need a wrapper in the first place.
Hiding members is good. But when you let the user edit/see them, you should impose some constraints: in each setter there should be a check before assigning the element a new value (which might even make your application crash).
Otherwise, there is little difference if the data was public.
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.