Say I'm using a C API that lets you register callbacks that take a void* closure:
void register_callback(void (*func)(void*), void *closure);
In C++ it's nice to have stronger types than void* so I want to create a wrapper that lets me register strongly-typed C++ callbacks instead:
template <typename T, void F(T*)>
void CallbackWrapper(void *p) {
return F(static_cast<T*>(p));
}
void MyCallback(int* param) {}
void f(void *closure) {
register_callback(CallbackWrapper<int, MyCallback>, closure);
}
This works alright. One nice property of this solution is that it can inline my callback into the wrapper, so this wrapping scheme has zero overhead. I consider this a requirement.
But it would be nice if I could make the API look more like this:
void f2() {
RegisterCallback(MyCallback, closure);
}
I hope I can achieve the above by inferring template parameters. But I can't quite figure out how to make it work. My attempt so far is:
template <typename T>
void RegisterCallback(void (*f)(T*), T* closure) {
register_callback(CallbackWrapper<T, f>, closure);
}
But this doesn't work. Anyone have a magic incantation that will make f2() work above, while retaining the zero-overhead performance characteristic? I want something that will work in C++98.
This template function improves the syntax marginally.
template <typename T, void F(T*)>
void RegisterCallback (T *x) {
register_callback(CallbackWrapper<T, F>, x);
}
int x = 4;
RegisterCallback<int, MyCallback>(&x);
If you are willing to use a functor rather than a function to define your callback, then you can simplify things a bit more:
#ifdef HAS_EXCEPTIONS
# define BEGIN_TRY try {
# define END_TRY } catch (...) {}
#else
# define BEGIN_TRY
# define END_TRY
#endif
template <typename CB>
void CallbackWrapper(void *p) {
BEGIN_TRY
return (*static_cast<CB*>(p))();
END_TRY
}
struct MyCallback {
MyCallback () {}
void operator () () {}
};
template <typename CB>
void RegisterCallback (CB &x) {
register_callback(CallbackWrapper<CB>, &x);
}
MyCallback cb;
RegisterCallback(cb);
But, as others have mentioned, you run the risk of the code not porting correctly to a system where the C ABI and C++ ABI differ.
I have discovered a better answer to this question than the other answers given to me here! (Actually it was another engineer inside Google who suggested it).
You have to repeat the function name twice, but that can be solved with a macro.
The basic pattern is:
// Func1, Func2, Func3: Template classes representing a function and its
// signature.
//
// Since the function is a template parameter, calling the function can be
// inlined at compile-time and does not require a function pointer at runtime.
// These functions are not bound to a handler data so have no data or cleanup
// handler.
template <class R, class P1, R F(P1)>
struct Func1 {
typedef R Return;
static R Call(P1 p1) { return F(p1); }
};
// ...
// FuncSig1, FuncSig2, FuncSig3: template classes reflecting a function
// *signature*, but without a specific function attached.
//
// These classes contain member functions that can be invoked with a
// specific function to return a Func/BoundFunc class.
template <class R, class P1>
struct FuncSig1 {
template <R F(P1)>
Func1<R, P1, F> GetFunc() { return Func1<R, P1, F>(); }
};
// ...
// Overloaded template function that can construct the appropriate FuncSig*
// class given a function pointer by deducing the template parameters.
template <class R, class P1>
inline FuncSig1<R, P1> MatchFunc(R (*f)(P1)) {
(void)f; // Only used for template parameter deduction.
return FuncSig1<R, P1>();
}
// ...
// Function that casts the first parameter to the given type.
template <class R, class P1, R F(P1)>
R CastArgument(void *c) {
return F(static_cast<P1>(c));
}
template <class F>
struct WrappedFunc;
template <class R, class P1, R F(P1)>
struct WrappedFunc<Func1<R, P1, F> > {
typedef Func1<R, void*, CastArgument<R, P1, F> > Func;
};
template <class T>
generic_func_t *GetWrappedFuncPtr(T func) {
typedef typename WrappedFunc<T>::Func Func;
return Func().Call;
}
// User code:
#include <iostream>
typedef void (generic_func_t)(void*);
void StronglyTypedFunc(int *x) {
std::cout << "value: " << *x << "\n";
}
int main() {
generic_func_t *f = GetWrappedFuncPtr(
MatchFunc(StronglyTypedFunc).GetFunc<StronglyTypedFunc>());
int x = 5;
f(&x);
}
This is not short or simple, but it is correct, principled, and standard-compliant!
It gets me what I want:
The user gets to write StronglyTypedFunc() taking a pointer to a specific thing.
This function can be called with a void* argument.
There is no virtual function overhead or indirection.
Why not make your closure a real closure (by including real typed state).
class CB
{
public:
virtual ~CB() {}
virtual void action() = 0;
};
extern "C" void CInterface(void* data)
{
try
{
reinterpret_cast<CB*>(data)->action();
}
catch(...){}
// No gurantees about throwing exceptions across a C ABI.
// So you need to catch all exceptions and drop them
// Or probably log them
}
void RegisterAction(CB& action)
{
register_callback(CInterface, &action);
}
By using an object you can introduce real state.
You have a clean C++ interface with correctly types objects.
Its easy to use you just derive from CB and implement action().
This also has the same number of actual function calls as you use. Because in your example you pass a function pointer to the wrapper (which can't be inlined (it can but it will take more static analysis then current compilers do)).
Apparently it does inline.
Related
I'm writing a simple "wrapper library" around another library and I'm having issues with std::function not being able to deduce template arguments for variadic template functions. To make things more concrete:
There's a library (it's a HTTP server) that I'm planning to "expand" with more functionality and to make it more convenient to use by "other code users" (automatic serialization of data, writing controller functions based on needs etc.). Basically cutting down on a lot of boilerplate code. From now on I'm calling this one simply "library". It cannot be touched or changed.
There's the code that "expands" the functionality above that I write myself and it's where I have the problem. From now on I call this a "wrapper library".
There's the "user code", that is - any code that uses the "wrapper library". I've included examples what I'd like it to look like and I'd rather keep it as simple as possible, especially when it comes to unnecessary template parameters bloat (not having to explicitly pass template arguments when it can be deduced by the compiler etc.). See main in the code below for examples.
Here's the complete example (that doesn't compile):
#include <type_traits>
#include <variant>
#include <vector>
/*** Library code starts here ***/
// Library handler function definition to be registered. This cannot be changed.
// For simplicity I made the function arguments (int, int) to denote that this
// handler function does take some arguments passed later by the library.
// In reality these are simple, non-templated structs.
using LibraryHandler = std::function<void(int, int)>;
std::vector<LibraryHandler> g_libraryHandlers;
void RegisterLibraryHandler(LibraryHandler handler)
{
// Library code registering passed handler. This cannot be changed.
g_libraryHandlers.push_back(handler);
}
/*** End of library code ***/
/*** My "wrapper library" starts here ***/
// ReturnType is the type returned by the functions written by "wrapper library users".
// Types... is the list of all possible types held by 'ReturnType' that a given function is allowed to return.
template<typename T, typename... Types>
static inline constexpr bool isConstructible = (std::is_constructible_v<T, Types> || ...);
template<typename T, typename... Types>
static inline constexpr bool isAssignable = (std::is_assignable_v<T&, Types> || ...);
template<typename... Types>
class ReturnType
{
public:
template<typename T, std::enable_if_t<
isConstructible<T, Types...> &&
isAssignable<T, Types...>,
int> = 0>
static ReturnType Build(const T& data)
{
return ReturnType(data);
}
private:
template<typename T>
ReturnType(const T& data) : m_data(data) { }
std::variant<Types...> m_data;
};
template<typename T>
class ParamType
{
public:
ParamType() { }
const T& GetData() const { return m_data; }
private:
T m_data;
};
/*** This is where my problem is - how to write these functions to allow for
different logic (based on passed function signature) inside nested lambda? ***/
// Version registering functions taking no arguments
template<typename... Types>
void RegisterFunction(std::function<ReturnType<Types...>()> func)
{
auto wrapperLambda = [func](int a, int b) { // Construct lambda to conform with library interface ('LibraryHandler')
// Logic specific for 'func' with signature: ReturnType<Types...>() - step before call
func();
// Logic specific for 'func' with signature: ReturnType<Types...>() - step after call
};
RegisterLibraryHandler(wrapperLambda); // Register lambda inside library
}
// Version registering functions taking arguments through 'ParamType'
template<typename... Types, typename TParam>
void RegisterFunction(std::function<ReturnType<Types...>(const ParamType<TParam>)> func)
{
auto wrapperLambda = [func](int a, int b) { // Construct lambda to conform with library interface ('LibraryHandler')
// Logic specific for 'func' with signature: ReturnType<Types...>(const ParamType<TParam>) - step before call
func();
// Logic specific for 'func' with signature: ReturnType<Types...>(const ParamType<TParam>) - step after call
};
RegisterLibraryHandler(wrapperLambda); // Register lambda inside library
}
// Version registering functions taking library arguments directly
template<typename... Types, typename TParam>
void RegisterFunction(std::function<ReturnType<Types...>(int, int)> func)
{
auto wrapperLambda = [func](int a, int b) { // Construct lambda to conform with library interface ('LibraryHandler')
// Logic specific for 'func' with signature: ReturnType<Types...>(int, int) - step before call
func(a, b);
// Logic specific for 'func' with signature: ReturnType<Types...>(int, int) - step after call
};
RegisterLibraryHandler(wrapperLambda); // Register lambda inside library
}
/*** End of my "wrapper library" ***/
/*** This is how I'd like the "users of the wrapper library" to write the code ***/
struct SomeReturnData { char a; char b; };
struct OtherReturnData { char c; char d; };
struct SomeParameterType { int p; };
// Example 1 - function only ever returning a single type, taking no arguments
ReturnType<SomeReturnData> UserFunctionNoArgs()
{
SomeReturnData data{ 'x', 'y' };
return ReturnType<SomeReturnData>::Build(data);
}
// Example 2 - function taking parameter 'SomeParameterType' and returning 'SomeReturnData' or 'OtherReturnData'
// based on contents of passed argument.
ReturnType<SomeReturnData, OtherReturnData> UserFunctionArgs(const ParamType<SomeParameterType> param)
{
if (param.GetData().p == 1000)
return ReturnType<SomeReturnData, OtherReturnData>::Build(SomeReturnData());
return ReturnType<SomeReturnData, OtherReturnData>::Build(OtherReturnData());
}
// Example 3 - function requesting library arguments to be passed directly
ReturnType<SomeReturnData, OtherReturnData> UserHandlingLibraryDirectly(int libraryArg1, int libraryArg2)
{
if (libraryArg1 == libraryArg2)
return ReturnType<SomeReturnData, OtherReturnData>::Build(SomeReturnData());
return ReturnType<SomeReturnData, OtherReturnData>::Build(OtherReturnData());
}
int main()
{
// User registers written functions in the "wrapper library".
// This includes any 'regluar functions'...
RegisterFunction(UserFunctionNoArgs);
RegisterFunction(UserFunctionArgs);
RegisterFunction(UserHandlingLibraryDirectly);
// ... or lambdas with captures (all possible parameter combinations from examples above apply).
int someInt = 123;
auto userLambda = [someInt]() -> ReturnType<SomeReturnData, OtherReturnData> {
if(someInt < 100)
return ReturnType<SomeReturnData, OtherReturnData>::Build(SomeReturnData());
return ReturnType<SomeReturnData, OtherReturnData>::Build(OtherReturnData());
};
return 0;
}
My issue is with the RegisterFunction above - I'd basically want to write it the way it is above, which is obviously not possible (the compiler complains about not being able to deduce template parameters). My goal is to not change / cut down on possibilities / make any more complicated anything that's inside main.
Lambdas are not std::function, so cannot be deduced. Fortunately, std::function has CTAD (c++17) allowing to solve your issue with an extra overload:
template<typename Func>
void RegisterFunction(Func func)
{
RegisterFunction(std::function{func}); // forward to overload taking std::function
}
Demo
I've just got confused how to implement something in a generic way in C++. It's a bit convoluted, so let me explain step by step.
Consider such code:
void a(int) {
// do something
}
void b(int) {
// something else
}
void function1() {
a(123);
a(456);
}
void function2() {
b(123);
b(456);
}
void test() {
function1();
function2();
}
It's easily noticable that function1 and function2 do the same, with the only different part being the internal function.
Therefore, I want to make function generic to avoid code redundancy. I can do it using function pointers or templates. Let me choose the latter for now. My thinking is that it's better since the compiler will surely be able to inline the functions - am I correct? Can compilers still inline the calls if they are made via function pointers? This is a side-question.
OK, back to the original point... A solution with templates:
void a(int) {
// do something
}
void b(int) {
// something else
}
template<void (*param)(int) >
void function() {
param(123);
param(456);
}
void test() {
function<a>();
function<b>();
}
All OK. But I'm running into a problem: Can I still do that if a and b are generics themselves?
template<typename T>
void a(T t) {
// do something
}
template<typename T>
void b(T t) {
// something else
}
template< ...param... > // ???
void function() {
param<SomeType>(someobj);
param<AnotherType>(someotherobj);
}
void test() {
function<a>();
function<b>();
}
I know that a template parameter can be one of:
a type,
a template type,
a value of a type.
None of those seems to cover my situation. My main question is hence: How do I solve that, i.e. define function() in the last example?
(Yes, function pointers seem to be a workaround in this exact case - provided they can also be inlined - but I'm looking for a general solution for this class of problems).
In order to solve this problem with templates, you have to use a template template parameter.
Unfortunately, you cannot pass template template function as a type, because it has to be instantiated first. But there is a workaround with dummy structures. Here is an example:
template <typename T>
struct a {
static void foo (T = T ())
{
}
};
template <typename T>
struct b {
static void foo (T = T ())
{
}
};
struct SomeObj {};
struct SomeOtherObj {};
template <template <typename P> class T>
void function ()
{
T<SomeObj>::foo ();
T<SomeOtherObj>::foo ();
}
int main ()
{
function<a>();
function<b>();
}
With generic lambda from C++14 you might do:
template<typename T> void a(T t) { /* do something */}
template<typename T> void b(T t) { /* something else */ }
template <typename F>
void function(F&& f) {
f(someobj);
f(someotherobj);
}
void test() {
// For simple cases, auto&& is even probably auto or const auto&
function([](auto&& t){ a(t); });
function([](auto&& t){ b(t); });
// For perfect forwarding
function([](auto&& t){ a(std::forward<decltype(t)>(t)); });
function([](auto&& t){ b(std::forward<decltype(t)>(t)); });
}
Can compilers still inline the calls if they are made via function pointers?
They can, but it is indeed more complicated, and they may fail more often than with functor or template.
Here's a way. It may not be the best, but it works:
template <typename T, T param>
void function() {
param(123);
param(456);
}
void test()
{
function< void(*)(int), a<int> >(); // space at end necessary to compiler
function< void(*)(int), b<int> >(); // because the C++ grammar is ambiguous
}
Whether or not they'll be inlined depends on the compiler, but I would be rather surprised if they weren't.
EDIT: Okay, I'm a little off today and missed the part where the parameters are of different types. My bad.
There may be a tricky way to do this with templates, but this is the easiest way I could think of:
#define function(x) do { x<thing1>(obj1); x<thing2>(obj2) } while(0)
I know, I know, "macros are evil," blah blah blah. It works. If function needs to be more complicated than your example you may run into problems, but it is much easier than anything I've been able to come up with.
template < typename F >
void function(F f)
{
f(123);
}
void a(int x) { ... }
struct b { void operator() (int x) { ... } };
void outer()
{
function(&a);
function(b());
}
I have a class with a unique_ptr member.
class Foo {
private:
std::unique_ptr<Bar> bar;
...
};
The Bar is a third party class that has a create() function and a destroy() function.
If I wanted to use a std::unique_ptr with it in a stand alone function I could do:
void foo() {
std::unique_ptr<Bar, void(*)(Bar*)> bar(create(), [](Bar* b){ destroy(b); });
...
}
Is there a way to do this with std::unique_ptr as a member of a class?
Assuming that create and destroy are free functions (which seems to be the case from the OP's code snippet) with the following signatures:
Bar* create();
void destroy(Bar*);
You can write your class Foo like this
class Foo {
std::unique_ptr<Bar, void(*)(Bar*)> ptr_;
// ...
public:
Foo() : ptr_(create(), destroy) { /* ... */ }
// ...
};
Notice that you don't need to write any lambda or custom deleter here because destroy is already a deleter.
It's possible to do this cleanly using a lambda in C++11 (tested in G++ 4.8.2).
Given this reusable typedef:
template<typename T>
using deleted_unique_ptr = std::unique_ptr<T,std::function<void(T*)>>;
You can write:
deleted_unique_ptr<Foo> foo(new Foo(), [](Foo* f) { customdeleter(f); });
For example, with a FILE*:
deleted_unique_ptr<FILE> file(
fopen("file.txt", "r"),
[](FILE* f) { fclose(f); });
With this you get the benefits of exception-safe cleanup using RAII, without needing try/catch noise.
You just need to create a deleter class:
struct BarDeleter {
void operator()(Bar* b) { destroy(b); }
};
and provide it as the template argument of unique_ptr. You'll still have to initialize the unique_ptr in your constructors:
class Foo {
public:
Foo() : bar(create()), ... { ... }
private:
std::unique_ptr<Bar, BarDeleter> bar;
...
};
As far as I know, all the popular c++ libraries implement this correctly; since BarDeleter doesn't actually have any state, it does not need to occupy any space in the unique_ptr.
Unless you need to be able to change the deleter at runtime, I would strongly recommend using a custom deleter type. For example, if use a function pointer for your deleter, sizeof(unique_ptr<T, fptr>) == 2 * sizeof(T*). In other words, half of the bytes of the unique_ptr object are wasted.
Writing a custom deleter to wrap every function is a bother, though. Thankfully, we can write a type templated on the function:
Since C++17:
template <auto fn>
struct deleter_from_fn {
template <typename T>
constexpr void operator()(T* arg) const {
fn(arg);
}
};
template <typename T, auto fn>
using my_unique_ptr = std::unique_ptr<T, deleter_from_fn<fn>>;
// usage:
my_unique_ptr<Bar, destroy> p{create()};
Prior to C++17:
template <typename D, D fn>
struct deleter_from_fn {
template <typename T>
constexpr void operator()(T* arg) const {
fn(arg);
}
};
template <typename T, typename D, D fn>
using my_unique_ptr = std::unique_ptr<T, deleter_from_fn<D, fn>>;
// usage:
my_unique_ptr<Bar, decltype(&destroy), destroy> p{create()};
You know, using a custom deleter isn't the best way to go, as you will have to mention it all over your code.
Instead, as you are allowed to add specializations to namespace-level classes in ::std as long as custom types are involved and you respect the semantics, do that:
Specialize std::default_delete:
template <>
struct ::std::default_delete<Bar> {
default_delete() = default;
template <class U>
constexpr default_delete(default_delete<U>) noexcept {}
void operator()(Bar* p) const noexcept { destroy(p); }
};
And maybe also do std::make_unique():
template <>
inline ::std::unique_ptr<Bar> ::std::make_unique<Bar>() {
auto p = create();
if (!p)
throw std::runtime_error("Could not `create()` a new `Bar`.");
return { p };
}
You can simply use std::bind with a your destroy function.
std::unique_ptr<Bar, std::function<void(Bar*)>> bar(create(), std::bind(&destroy,
std::placeholders::_1));
But of course you can also use a lambda.
std::unique_ptr<Bar, std::function<void(Bar*)>> ptr(create(), [](Bar* b){ destroy(b);});
#include "fmt/core.h"
#include <memory>
class example {};
void delete_example(example *)
{
fmt::print("delete_example\n");
}
using example_handle = std::unique_ptr<example, decltype([] (example * p)
{
delete_example(p);
})>;
int main()
{
example_handle handle(new example);
}
Just my two cents, using C++20.
https://godbolt.org/z/Pe3PT49h4
With a lambda you can get the same size as a plain std::unique_ptr. Compare the sizes:
plain: 8
lambda: 8
fpointer: 16
std::function: 40
Which is the output of the following. (I declared the lambda outside the scope of the class. Not sure if you can scope it inside the class.)
#include <iostream>
#include <memory>
#include <functional>
struct Bar {};
void destroy(Bar* b) {}
Bar* create() { return 0; }
auto lambda_destroyer = [](Bar* b) {destroy(b);};
class Foo {
std::unique_ptr<Bar, decltype(lambda_destroyer)> ptr_;
public:
Foo() : ptr_(create(), lambda_destroyer) { /* ... */ }
};
int main()
{
std::cout << "plain: " << sizeof (std::unique_ptr<Bar>) << std::endl
<< "lambda: " << sizeof (std::unique_ptr<Bar, decltype(lambda_destroyer)>) << std::endl
<< "fpointer: " << sizeof (std::unique_ptr<Bar, void(*)(Bar*)>) << std::endl
<< "std::function: " << sizeof (std::unique_ptr<Bar, std::function<void(Bar*)>>) << std::endl;
}
I'm fairly convinced that this is the best current way to do it:
#include <memory>
#include <stdio.h>
template <typename T, auto fn>
struct Deleter
{
void operator()(T *ptr)
{
fn(ptr);
}
};
template <typename T, auto fn>
using handle = std::unique_ptr<T, Deleter<T, fn>>;
using file = handle<FILE, fclose>;
int main()
{
file f{fopen("a.txt", "w")};
return 0;
}
Because you've specified a Functor as the deleter in the unique_ptr's template arguments, you don't need to set a deleter when calling its constructor.
The Deleter functor uses "template auto" to take a deletion function (in this example: fclose) as a template argument, so this needs C++17.
Expanding it to support other types is just one extra "using" line per type.
Simple is also:
class Foo {};
class Bar
{
public:
Bar()
{
// actual initialisation at some point
}
private:
std::unique_ptr<Foo, void(*)(Foo*)> foo = {{}, {}}; // or = {nullptr, {}}
};
Sure, you can also create some helper function to do the job to not have the initial state at any time.
In fact, in your specific scenario, the cleanest way is to actually put your Bar (not mine, sorry for the confusion) into a simple wrapper class, which makes reuse easier.
There are two "C" functions:
void fooA(const char*);
void fooW(const wchar_t*);
Then there is a wrapper template function:
template<typename _TChar>
void foo(const _TChar* str)
{
// call fooA or fooB based on actual type of _TChar
// std::conditional .. ?
// fooA(str);
// fooW(str);
}
If the caller calls foo("Abc"), this template function should make a compile-time call to fooA. Similiarly, foo(L"Abc") should make the final call to fooW.
How do I do that? I thought of using std::conditional but couldn't make it.
I cannot make fooA or fooB overloaded, since these are C functions.
You can put all your wchar_t versions in a class template, say overloads and their char counter-parts in its specialization as shown below:
template<typename WideCharVersion>
struct overloads
{
void foo(wchar_t const * arg)
{
FooW(arg);
}
//more wchar_t functions
};
template<>
struct overloads<std::false_type>
{
void foo(char const * arg)
{
FooA(arg);
}
//more char functions
};
//a friendly alias!
template<typename T>
using is_wide_char = typename std::is_same<whar_t, T>::type;
And then you can use them as:
template<typename _TChar>
void foo(const _TChar* str)
{
overloads<is_wide_char<_TChar>>::foo(str);
}
Expression SFINAE makes it easy!
Other way is to use Expression SFINAE which does not require to you write anything like overloads and does the same job with less code:
template<typename _TChar>
void foo(const _TChar* str)
{
invokeOne(fooA, fooW, str);
}
And then you can implement invokeOne as:
template<typename F1, typename F2, typename ... Args>
auto invokeOne(F1 f1, F2 f2, Args && ... args) -> decltype(f1(args...))
{
return f1(args...);
}
template<typename F1, typename F2, typename ... Args>
auto invokeOne(F1 f1, F2 f2, Args && ... args) -> decltype(f2(args...))
{
return f2(args...);
}
Have a look at the online demo.
In this approach, you don't have to add the overloads to the overloads class template and to its specialization. Instead you just pass them as arguments to invokeOne which calls the right overload for you.
Hope that helps.
Then overload another function. I'm assuming foo does more work and needs to be a template. Then call foo_forward_call, defined as such:
void foo_forward_call(char const* ptr) {
FooA(ptr);
}
void foo_forward_call(wchar_t const* ptr) {
FooW(ptr);
}
and at the call site:
template<typename _TChar>
void foo(const _TChar* str)
{
foo_forward_call(str);
}
in C++1z you'll be able to use constexpr if, but to be honest, I think that overloaded solution is still more readable.
template<typename _TChar>
void foo(const _TChar* str)
{
if constexpr(std::is_same<_TChar, char>::value) {
FooA(str);
} else {
FooW(str);
}
}
Alternatively, you can use Boost.Hana's overload:
template<typename _TChar>
void foo(const _TChar* str)
{
hana::overload(fooA, fooW)(str);
}
demo
By the way: you should eschew using underscore-capital-letter names in your programs. They're reserved for implementation for any use (i.e. macros) and might lead to nasty name clashes.
This seems like a really strange thing to do with templates. I would suggest using normal overloading instead:
void foo(const char* p) { fooA(p); }
void foo(const wchar_t* p) { fooW(p); }
If you insist on using template then you can do it like this:
template <typename T>
void foo(const T* p)
{
// Declare functions here so that calling fooW with const char*
// and 'calling' fooA with const wchar_t* would not cause compile error.
void fooA(const T*);
void fooW(const T*);
if (std::is_same<char, T>::value)
fooA(p);
else
fooW(p);
}
I like solving problems in general. So let us design a mechanism to overload stuff.
overload_t<...> takes a set of callables in ... and generates an object which uses standard overload resolution to choose between them, via inheritance of operator():
template<class...Fs>
struct overload_t;
// the case where we have a function object:
template<class F>
struct overload_t<F>:F{
overload_t(F f):F(std::move(f)){}
using F::operator();
// boilerplate to ensure these are enabled if possible:
overload_t(overload_t&&)=default;
overload_t(overload_t const&)=default;
overload_t& operator=(overload_t&&)=default;
overload_t& operator=(overload_t const&)=default;
};
// we cannot inherit from a function pointer. So
// store one, and write an `operator()` that forwards to it:
template<class R, class...Args>
struct overload_t<R(*)(Args...)>{
using F=R(*)(Args...);
F f;
overload_t(F fin):f(fin){}
R operator()(Args...args)const{
return f(std::forward<Args>(args)...);
}
overload_t(overload_t&&)=default;
overload_t(overload_t const&)=default;
overload_t& operator=(overload_t&&)=default;
overload_t& operator=(overload_t const&)=default;
};
// the case where we have more than type to overload.
// recursively inherit from the one-arg and the rest-of-arg
// and using operator() to bring both of their () into equal standing:
template<class F0, class...Fs>
struct overload_t<F0,Fs...>:
overload_t<F0>,
overload_t<Fs...>
{
using overload_t<F0>::operator();
using overload_t<Fs...>::operator();
overload_t(F0 f0, Fs...fs):
overload_t<F0>(std::move(f0)),
overload_t<Fs...>(std::move(fs)...)
{}
overload_t(overload_t&&)=default;
overload_t(overload_t const&)=default;
overload_t& operator=(overload_t&&)=default;
overload_t& operator=(overload_t const&)=default;
};
// a helper function to create an overload set without
// having to specify types. Will be obsolete in C++17:
template<class...Fs>
overload_t<Fs...> overload(Fs...fs){ return {std::move(fs)...};}
Now to generate a single object that is an overload of multiple, do this:
overload(FooA,FooW)( str );
And str will be dispatched to either based on the usual overload resolution rules. This is useful elsewhere which is why it is worth writing, and the code at point of use is self documenting.
Live example (wow, wrote it correct the first time!)
There are a number of improvements one can add to the above overload_t.
Perfect forwarding of the fs during construction and in the helper function.
Balanced Binary tree inheritance instead of linear (important of more than a few overloads are done). This can have runtime and compiletime performance impliciations, especially for a large number of functions.
Introspect incoming Fs; if they are overload_t balance the combined tree.
In C++17, a func<auto> template that takes a function pointer and returns a function object that statelessly invokes it. Compilers are relatively good at eliding function pointers, but they are better at it when there is no possible runtime state that could alter them.
Deciding what to do for overload_t<>. Currently it fails to compile; maybe it should just be an empty struct {}, or even a struct with an uncallable operator().
Examine existing libraries, like boost::hana::overload and see what differences there are.
Expose the ability to extract which of the overloads would be called, maybe via a static tag_t<F> which_overload_helper( Args... ) const method and template<class...Args> using which_overload = typename decltype( which_overload_helper( std::declval<Args>()... ) )::type;
Properly picking overloads when some of the incoming Fss do/do not have a const operator(). Should the function pointer have const, volatile, both or neither on operator()? All 4? How about && vs & overloads?
Maybe if there were more targetted functions or overloading wasn't the only problem you were trying to solve then it might be worthwhile using templates to get this done.
In this case though, simply write your overloads:
void foo(const char* x) { fooA(x); }
void foo(const wchar_t* x) { fooW(x); }
You have a few options.
Use an helper explicitly specialized struct:
template <typename>
struct helper;
template<>
struct helper<char>
{
void operator()(const char* x){ FooA(x); }
};
template<>
struct helper<wchar_t>
{
void operator()(const wchar_t* x){ FooW(x); }
};
template <typename _TChar>
void foo(const _TChar* str)
{
helper<_TChar>{}(str);
}
Use a "static if" implementation (e.g. boost::hana::eval_if or my own):
template <typename _TChar>
void foo(const _TChar* str)
{
vrm::core::static_if(std::is_same<_TChar, char>{})
.then([](const auto* x_str){ FooA(x_str); })
.else_([](const auto* x_str){ FooW(x_str); })(str);
}
Use an helper overloaded function:
void helper(const char* x) { FooA(x); }
void helper(const wchar_t* x) { FooW(x); }
template <typename _TChar>
void foo(const _TChar* str)
{
helper(str);
}
I think using typeid() is very elegant and readable, but not sure if there is any side effect.
#include <typeinfo>
template <typename T>
void foo(){
if(typeid(T) == typeid(const char*)){
fooA();
}
else if (typeid(T) == typeid(const wchar_t*)){
fooB();
}
}
Check it out in wandbox.
I am trying to simplify (via make_fn()) the generation of functors that preprocess parameters (via wrap()) for member functions of arity n.
Generating the functors is basically working, but until now only by explicitly specifying the parameter types for the member function.
Now i'd like to generate the correct functor from the member function type it handles:
struct X {};
template<class C, typename T1, bool (C::*F)(T1)>
inline // there are more for T1..TN
bool wrap(C* c, X x)
{
return (c->*F)(process<T1>(x));
}
template<class C, typename T1, bool (C::*F)(T1)>
inline // there are more for T1..TN
boost::function<bool (C*, X)> make_fn(F f) // <- problem here, F is not a type
{
return boost::bind(&wrap<C, T1, F>, _1, _2);
}
With this however, vc++ and g++ don't see F as a type for the parameter of make_fn(). I must miss something obvious here and am feeling somewhat blind.
The idea was that it should work like this:
struct A
{
bool f1(bool) { return true; }
};
void test()
{
A a;
X x;
make_fn(&A::f1)(&a, x);
}
Any ideas on how to make that work?
Background:
I have a fixed interface which, when simplified, looks like this:
bool invoke(C* c, const char* const functionName, int argCount, X* args);
X is a variant type which i have to convert to certain backend types (int, std::string, ...).
To handle these calls i have a map of functors that are looked up by name and map these calls to member functions of some instance.
The intention of the wrapping is to avoid manual conversions and instead generate functors which do the conversion for me or throw. I have this working with a macro based solution, but that solution requires to specify the types and the parameter count explicitly.
Via function overload resolution i hope to generate the correct converting functor implicitly from the member function signature.
It appears to me that you are attempting to turn a pointer passed to a function into a non-type template argument, which I'm afraid is not going to work (see comments to your question).
What you could do, is to store the function pointer in a function object. The following appears to compile:
#include <boost/bind.hpp>
#include <boost/function.hpp>
struct X {};
template <class T>
bool process(X) { return true; }
template <class C, class T1, class Func>
struct wrap1
{
typedef bool result_type;
Func f;
wrap1(Func f): f(f) {}
bool operator()(C* c, X x)
{
return (c->*f)(process<T1>(x));
}
};
template<class C, typename T1>
inline // there are more for T1..TN
boost::function<bool (C*, X)> make_fn(bool (C::*f)(T1))
{
return boost::bind(wrap1<C, T1, bool (C::*)(T1)>(f), _1, _2);
}
struct A
{
bool f1(bool) { return true; }
};
void test()
{
A a;
X x;
make_fn(&A::f1)(&a, x);
}
However, I'm not sure if that is any good and how you would create the rest of the wrappers. For the latter you might just get a compiler that supports variadic templates. :)