Following (generic) situation:
I am trying to call another constexpr member-function within a class, but I get the error that 'this' is not a constant expression. The question I now have is (as I am new to the constexpr idiom), is if such a use-case is not allowed. Otherwise, how would I fix it?
#include <iostream>
class cc
{
public:
cc()=default;
~cc()=default;
// public method to call th eprivate constexpr functions
template<int varbase>
constexpr void doSomething()
{
static_assert(varbase>0, "varbase has to be greater zero");
// nested call to constexpr functions
char x=testM2<testM1<varbase>()>();
}
private:
template<int var1>
constexpr int testM1()
{
int temp=var1;
return (++temp);
}
template<int var2>
constexpr char testM2()
{
int temp=var2;
if (temp==2)
return 'A';
else
return 'B';
}
};
int main()
{
cc obj;
obj.doSomething<1>();
return 0;
}
Run the above example
So constexpr does not mean "this function can only be called at compile time". It means "this function may be called both at compile and run time".
char x=testM2<testM1<varbase>()>();
If called at run time, the value of this is not a compile time constant. So the result of a constexpr method call is not a compile time value, so its result cannot be used as a template argument.
If you are not using this (as you appear not to be) then marking testM2 etc. as static fixes your problem. If you are using this then there isn't a simple workaround; there is no way to say "this function will only be called at compile time". Any workaround will depend on details of what you are doing with this and the return value, if even possible. Write a new question with those details added.
The problem is that every instance of cc will have its own version of doSomething(), testM1() and testM2().
To solve it, the compiler will apply this in front of all the functions, to identify which instance of cc you are trying to refer to.
this is not a constant expression. It is evaluated at runtime.
That is why you are getting the error : 'this' is not a constant expression
To solve this problem, either move your constexpr functions outside the class, or mark these functions as static.
Here is a working revision of your code, which will work in C++11 as well.
#include <iostream>
template<int var1>
constexpr int testM1() // move these functions outside, if they use no data of class cc
{
return int{var1 + 1};
}
template<int var2>
constexpr char testM2()
{
return (var2 == 2) ? 'A' : 'B';
}
class cc
{
public:
cc()=default;
~cc()=default;
// public method to call the private constexpr functions
template<int varbase>
static constexpr void doSomething()
{
/* if you want to keep it inside class, mark it `static`
so that the compiler understands that it will be shared by all instances. */
static_assert(varbase>0, "varbase has to be greater zero");
// nested call to constexpr functions
constexpr char x = testM2<testM1<varbase>()>(); // preferably x should be `constexpr`
}
};
int main()
{
cc obj;
obj.doSomething<2>();
return 0;
}
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();
}
EDIT: Renamed, as my final solution does not use a poisoning method.
I'm looking for a way to prevent a constexpr method from being called at runtime. I'm writing a function that accepts a string literal, so I cannot simply use a NTTP as a way to require a constexpr parameter:
template<const char* str>
auto func() {...}
Because then even legitimate constexpr uses become cumbersome, requiring values to have static linkage, and you can't feed in a string literal. I want to do:
constexpr auto func(const char* str) {...}
The reason is because I check the string against a list of values, and want to STATICALLY check that the parameter is contained in the allowed set. I can do this easily: by just throw()'ing in a constexpr function, you can cause a compile-time error. But I do not want the possibility of generating production code with some branch that causes the program to exit at runtime. That would cause a major problem in my field; this feature is a nice-to-have in a program that does "other important stuff" and bad things happen if the program terminates.
I read about a whole bunch of possible ways to do this:
Use C++20 consteval - don't have C++20
Use C++20 std::is_constant_evaluated - don't have C++20
Poison the method at runtime by returning a result to an undefined symbol (e.g. extern int i that never gets defined). The compiler never creates code which returns that symbol if the method is called at compile-time, but it does if the method is called at runtime, resulting in a link error. Works, but ugly linker error; not my favorite. A version of that is shown in my post here: Constexpr functions not called at compile-time if result is ignored.
In C++17, noexcept gets automatically added onto any call to a constexpr function that actually gets called in a constexpr context. So you can do noexcept(foo(1)) vs noexcept(foo(i)) for constexpr int foo(int i) (not explicitly declared noexcept) to detect whether i causes the call to be constexpr/not. But you can't do that from within a constexpr function that has accepted some parameter - you need to do it from the call-site. So: probably requires a helper MACRO (not my favorite but it works).
Create a lambda whose return type is invalid if certain variables outside the scope of the lambda are not constexpr. This post goes into detail: https://stackoverflow.com/a/40413051
So I'm leaning towards using #3 or #4 + a macro, but ***this post is about #5 ***, or totally new ideas.
Can anyone come up with a way to do #5 without a lambda, for example? After that, I want to see if I can come up with a way to use it within the constexpr function itself rather than requiring it to be used from the call-site. For now, just try to poison a constexpr function if it is called at runtime, forget about "detecting" whether the function call is constexpr.
I can re-create the results of #5 by creating a lambda in main as the author did, but that's not actually very useful, and I'm still not convinced that it's fully legal. To start with, anything that can be done with a lambda can be done without a lambda -- right??? I can't even get the original author's method to work without a lambda. That seems like a first required step to get it to work outside of main().
Below are a couple ideas I've tried to recreate #5 without a lambda. Live example with a billion more permutations, none of which work: https://onlinegdb.com/B1oRjpTGP
// Common
template<int>
using Void = void;
// Common
struct Delayer {
constexpr auto delayStatic(int input) { return input; }
};
// Attempt 1
template<typename PoisonDelayer>
constexpr auto procurePoison(int i) {
struct Poison {
// error: use of parameter from containing function
// constexpr auto operator()() const -> Void<(PoisonDelayer::delayStatic(i), 0)> {}
} poison;
return poison;
}
// Attempt 2
struct PoisonInnerTemplate {
const int& _i;
// Internal compiler error / use of this in a constexpr
template<typename PoisonDelayer>
auto drink() const -> Void<(PoisonDelayer::delayStatic(_i), 0)> {}
};
int main()
{
auto attempt1 = procurePoison<Delayer>(1);
constexpr int i = 1;
auto attempt2 = PoisonInnerTemplate{i};
attempt2.drink<Delayer>();
return 0;
}
One more thing: I toyed with the idea of making a pre-defined list of allowed tags (wrap the string in a struct so it can be a NTTP), and putting them in some kind of container, and then having a method to retrieve them. The problems are: (1) the call-site syntax gets quite verbose to use them, (2) although it'd be fine for the call-site to use a syntax like MyTags::TAG_ONE, my program needs to be able to know the full set of tags, so they need to be in an array or a template variable, (3) using an array doesn't work, because getting an array element produces an rvalue, which doesn't have linkage, so can't be fed as a NTTP, (4) using a template variable with explicit specialization to define each tag requires the template variable to be global-scope, which doesn't work well for me...
This is about the best I can do - I think it's kind of ugly...:
struct Tag {
const char* name;
};
template<auto& tag>
void foo() {}
struct Tags {
static constexpr Tag invalid = {};
static constexpr Tag tags[] = {{"abc"}, {"def"}};
template<size_t N>
static constexpr Tag tag = tags[N];
template<size_t N = 0>
static constexpr auto& getTag(const char* name) {
if constexpr(N<2) {
if(string_view(name)==tag<N>.name) {
return tag<N>;
} else {
return getTag<N+1>(name);
}
} else {
return invalid;
}
}
};
int main()
{
foo<Tags::getTag("abc")>();
}
Here's my own answer, which checks that a string literal is within an allowed set at COMPILE-TIME, then performs an action based upon the value of that string. No poisoning of constexpr functions is needed, and there are still no cumbersome requirements to provide string literals with static linkage.
Credit goes to Jarod42 for "shorthand option 2", which uses a gcc extension for string template user-defined literals, which is part of C++20 but not C++17.
I think I'm happy enough with any of the three "shorthand" call-site syntaxes. I would still welcome any alternatives or improvements, or pointers on what I messed up. Perfect forwarding, etc. is left as an exercise for the reader ;-)
Live demo: https://onlinegdb.com/S1K_7sb7D
// Helper for Shorthand Option 1 (below)
template<typename Singleton>
Singleton* singleton;
// Helper to store string literals at compile-time
template<typename ParentDispatcher>
struct Tag {
using Parent = ParentDispatcher;
const char* name;
};
// ---------------------------------
// DISPATCHER:
// ---------------------------------
// Call different functions at compile-time based upon
// a compile-time string literal.
// ---------------------------------
template<auto& nameArray, typename FuncTuple>
struct Dispatcher {
FuncTuple _funcs;
using DispatcherTag = Tag<Dispatcher>;
template<size_t nameIndex>
static constexpr DispatcherTag TAG = {nameArray[nameIndex]};
static constexpr DispatcherTag INVALID_TAG = {};
Dispatcher(const FuncTuple& funcs) : _funcs(funcs) {
singleton<Dispatcher> = this;
}
template<size_t nameIndex = 0>
static constexpr auto& tag(string_view name) {
if(name == nameArray[nameIndex]) {
return TAG<nameIndex>;
} else {
if constexpr (nameIndex+1 < nameArray.size()) {
return tag<nameIndex+1>(name);
} else {
return INVALID_TAG;
}
}
}
static constexpr size_t index(string_view name) {
for(size_t nameIndex = 0; nameIndex < nameArray.size(); ++nameIndex) {
if(name == nameArray[nameIndex]) {
return nameIndex;
}
}
return nameArray.size();
}
constexpr auto& operator()(const char* name) const {
return tag(name);
}
template<auto& tag, typename... Args>
auto call(Args... args) const {
static constexpr size_t INDEX = index(tag.name);
static constexpr bool VALID = INDEX != nameArray.size();
static_assert(VALID, "Invalid tag.");
return get<INDEX*VALID>(_funcs)(args...);
}
};
template<auto& nameArray, typename FuncTuple>
auto makeDispatcher(const FuncTuple& funcs) {
return Dispatcher<nameArray, FuncTuple>(funcs);
}
// ---------------------------------
// SHORTHAND: OPTION 1
// ---------------------------------
// Use a singleton pattern and a helper to let a tag be associated with a
// specific dispatcher, so that the call-site need not specify dispatcher twice
// ---------------------------------
template<auto& tag, typename... Args>
auto call(Args... args) {
using Tag = remove_reference_t<decltype(tag)>;
using ParentDispatcher = typename Tag::Parent;
static auto dispatcher = singleton<ParentDispatcher>;
return dispatcher->template call<tag>(args...);
}
// ---------------------------------
// SHORTHAND: OPTION 2
// ---------------------------------
// Use a string template user-defined literal operator to shorten call-site syntax
// gcc supports this as an extension implementing proposal N3599 (standardized in C++20)
// If warnings occur, try pragma GCC diagnostic ignored "-Wgnu-string-literal-operator-template"
// ---------------------------------
// Need characters to be in contiguous memory on the stack (not NTTPs) for TAG_FROM_LITERAL
template<char... name>
constexpr char NAME_FROM_LITERAL[] = {name..., '\0'};
// Don't need to specify Dispatcher with user-defined literal method; will use dispatcher.check<>()
struct TagFromLiteral {};
// Need to have a constexpr variable with linkage to use with dispatcher.check<>()
template<char... name>
constexpr Tag<TagFromLiteral> TAG_FROM_LITERAL = {NAME_FROM_LITERAL<name...>};
// Create a constexpr variable with linkage for use with dispatcher.check<>(), via "MyTag"_TAG
template<typename Char, Char... name>
constexpr auto& operator"" _TAG() {
return TAG_FROM_LITERAL<name...>;
}
// ---------------------------------
// SHORTHAND: OPTION 3
// ---------------------------------
// Use a macro so the call-site need not specify dispatcher twice
// ---------------------------------
#define DISPATCH(dispatcher, name) dispatcher.call<dispatcher(name)>
// ---------------------------------
// COMMON: TEST FUNCTIONS
// ---------------------------------
bool testFunc1(int) { cout << "testFunc1" << endl; }
bool testFunc2(float) { cout << "testFunc2" << endl; }
bool testFunc3(double) { cout << "testFunc3" << endl; }
static constexpr auto funcs = make_tuple(&testFunc1, &testFunc2, &testFunc3);
static constexpr auto names = array{"one", "two", "three"};
int main()
{
// Create a test dispatcher
auto dispatcher = makeDispatcher<names>(funcs);
// LONG-HAND: call syntax: a bit verbose, but operator() helps
dispatcher.call<dispatcher("one")>(1);
// SHORTHAND OPTION 1: non-member helper, singleton maps back to dispatcher
call<dispatcher("one")>(1);
// SHORTHAND OPTION 2: gcc extension for string UDL templates (C++20 standardizes this)
dispatcher.call<"one"_TAG>(1);
// SHORHAND OPTION 3: Macro
DISPATCH(dispatcher, "one")(1);
return 0;
}
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.
I ran into the following code that defines a function template in a class:
#include <cstdint>
class foo {
public:
enum class magic_type : std::uint32_t {
START = 0,
BLUE = 0xFF000001,
RED,
};
struct header_t {
uint32_t version;
magic_type magic;
};
template <typename T>
static bool is_of_type(header_t *h)
{
return (h->magic == T::magic_type);
}
foo(uint32_t ver, foo::magic_type mag)
{
header.version = ver;
header.magic = mag;
}
header_t header;
};
I am finding the implementation of 'is_of_type` confusing. The code as is compiles, so syntactically must be correct. However, this method is not invoked from any other part of the program, so I am not sure what the intent of the function is (lack of documentation). I figured there could be two interpretation of the function:
Return true/false based on the magic type of an object and the specific enum type passed as the function template parameter.
E.g. An invocation of the method would be:
foo bar(1.2, foo::magic_type::BLUE);
bool temp = bar.is_of_type<foo::magic_type::BLUE>(&(bar.header));
However, in the above case, I am not really passing a type (as in an int, or char, etc). Right? The code does not compile.
Return true/false if the magic type is a valid enum.
In this case, I am assuming the function does not need to be templated, and could be re-written as:
static bool is_of_type(header_t *h)
{
return (h->magic == foo::magic_type);
}
E.g. of an invocation:
foo bar(1.2, foo::magic_type::BLUE);
bool temp = bar.is_of_type(&(bar.header));
Again, getting compile error. I tried using "typename", but my attempts were futile.
Can someone please help me with proper implementation of is_of_type for the above two cases and an invocation example.
The invocation would be with an explicitly specified type, which has a nested static member called magic_type.
For instance, it could be called as follows:
struct test {
static foo::magic_type const magic_type;
};
foo::magic_type const test::magic_type = 42;
foo bar{1, foo::magic_type::BLUE};
bar.is_of_type<test>(bar.header);
The fact that magic_type is used twice, once for an enum class and once for a static variable, is very confusing though.
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.