I was wondering if I write something like this:
Type &var = database.get<TYPE>(name);
Assuming that database is a container able to store datablocks of different datatypes. To get a reference to that datablock, the name as std::string is passed to get() so that at different places with that call I have a way to access certain 'global' variables. I have get() as a template method and I would like to keep it that way.
What I want to do is shorten that call an elegant way like this:
Type &var = database.get(name);
So the template deduction is automatically performed. Now I could create a macro for that, but this is not what I want to do, as I do not consider it elegant for such case.
That deduction though does not work, because we need a template parameter. Why can't the compiler take what is set for the variable and pass it as template parameter automatically? Is there a way to do this? I don't want to have any type conversions in this case. Can we omit it?
No, you can't do this---the rules of the language simply don't allow the compiler to take into account the declared type of var in order to perform the deduction. (Note that template arguments for a function template can be deduced when initializing a function pointer by taking the address of a function template. However, that's not what's happening in this case.)
However, you can easily avoid writing the type twice or inducing any undesirable conversions, by using auto:
auto& var = database.get<Type>(name);
Sorry, this is not possible. What you are trying to do is to have the return type of a templated function based on the value of its parameter.
This cannot work.
Automatic template deduction (like you mentioned) can only be performed, if the template parameter is obvious. For example:
template<_T> void func(_T param) { }
This can be called like
int a;
func(a); //instead of func<int>(a);
here the compiler knows exactly what you are trying to do.
Because all templates are resolved at compile time, there is no way of changig a methods return type based on any vague arguments.
You could have a look at boost::any, which does your Job quite well.
Related
Is it possible to "alias" std::get
in something like as
it would give something like bool v = as<bool>(my_variant);
from C++11: How to alias a function? I understand well that we can not use using because a function template is not a type.
from C++ How to create a function pointer to an overloaded templated function I understand that a function pointer can only be created from a specific template instantiation..
So I tend to say that this is not possible, but maybe I'm wrong ?
For functions and function templates, in C++, there are no proper aliases in the sense of the alias name immediately referring to the same entity as it aliases.
The closest thing is a function reference, which also only applies to individual specializations and still behaves like a reference, not an alias. Also, taking a pointer or reference to a standard library function has unspecified behavior in order to allow the implementation to modify the overload set. Only direct calls are generally specified.
Practically speaking implementing as as a new (set of) function templates that forward to std::get in their body is the best approach. The behavior of as can be made to be identical to that of std::get by copying all of std::get's specified signatures.
Also, it is generally impossible to alias templates. Type alias templates (template</*...*/> using MyAlias = /*...*/;) do not alias a class template with a new name. They are instead themselves separate templates and each specialization of that template is a single alias for a specific type.
I want to create the following types
using Function = std::function<Variant(int)>;
using Variant = std::variant<int, bool, Function>;
In Variant I need to have Function as well, but Function should return a Variant (by value). However I cannot find the right syntax. I was trying to forward-declare Function, but I'm not sure how to do this.
As far as I know, I should be able to write such a thing, because forward-declaration is usually enough regarding the return type of a function.
You can scaffold it, sure. You just cannot have both identifiers be aliases. An alias cannot be forward declared.
Something like this:
struct Variant;
using Function = std::function<Variant(int)>;
struct Variant : std::variant<int, bool, Function> {
using variant::variant;
};
Should work mostly as intended. The return type is incomplete initially (which should be okay so long as no operation is performed that requires it be complete). And then it's completed, by using the alias for Function.
The caveat is that Variant is now its own independent type. So some aspects of template argument deduction may work differently. But I doubt it's likely to rise up and bother you.
You also have the option of flipping the roles if needed. Be warned that the standard library may not be specified to behave reliably for types inheriting from its components. So some casting to a base class reference may be in order. Lay it out in the way that best works for you.
Consider this simple check for whether a (global) function is defined:
template <typename T>
concept has_f = requires ( const T& t ) { Function( t ); };
// later use in MyClass<T>:
if constexpr ( has_f<T> ) Function( value );
unfortunately this allows for implicit conversions. This is obviously a big risk for mess-ups.
Question: How to check if Function( const T& t ) 'explicitly' exists?
Something like
if constexpr ( std::is_same_v<decltype( Function( t ) ), void> )
should be free of implict conversions, but I can't get it working.
Note: The point of the concept approach was to get rid of old 'detection patterns' and simplify.
Before explaining how to do this, I will explain why you shouldn't want to do any of this.
You mentioned "old 'detection patterns'" without adding any specifics as to what you are referring to. There are a fair number of idioms C++ users sometimes employ that can do something like detecting if a function takes a particular parameter. Which ones of these count as "detection patterns" by your reckoning is not known.
However, the vast majority of these idioms exist to serve a specific, singular purpose: to see if a particular function call with a given set of arguments is valid, legal C++ code. They don't really care if a function exactly takes T; testing for T specifically is just how a few of those idioms work to produce the important information. Namely whether you can pass a T to said function.
Looking for a specific function signature was almost always a means to an end, not the final goal.
Concepts, particularly requires expressions, is the end itself. It allows you to ask the question directly. Because really, you don't care if Function has a parameter that takes a T; you care whether Function(t) is legitimate code or not. Exactly how that happens is an implementation detail.
The only reason I can think of that someone might want to constrain a template on an exact signature (rather than an argument match) is to defeat implicit conversion. But you really shouldn't try to break basic language features like that. If someone writes a type that is implicitly convertible to another, they have the right to the benefits of that conversion, as defined by the language. Namely, the ability to use it in many ways as if it were that other type.
That is, if Function(t) is what your constrained template code is actually going to do, then the user of that template has every right to provide code that makes that compiler within the limits of the C++ language. Not within the limits of your personal ideas of what features are good or bad in that language.
Concepts are not like base classes, where you decide the exact signature for each method and the user must strictly abide by that. Concepts are patterns that constrain template definitions. Expressions in concept constraints are expressions that you expect to use in your template. You only put an expression in a concept if you plan on using it in your templates constrained by that concept.
You don't use a function signature; you call functions. So you constrain a concept on what functions can be called with which arguments. You're saying "you must let me do this", not "provide this signature".
That having been said... what you want is not generally possible ;)
There are several mechanisms that you might employ to achieve it, but none of them do exactly what you want in all cases.
The name of a function resolves to an overload set consisting of all of the functions that could be called. This name can be converted into a pointer to a specific function signature if and only if that signature is one of the functions in the overload set. So in theory, you might do this:
template <typename T>
concept has_f = requires () { static_cast<void (*)(T const&)>(&Function); };
However, because the name Function is not dependent on T (as far as C++ is concerned), it must be resolved during the first pass of two-phase name lookup for templates. That means any and all Function overloads you intend to care about have to be declared before has_f is defined, not merely instantiated with an appropriate T.
I think this is sufficient to declare that this is non-functional as a solution. Even if it worked though, it would only "work" given 3 circumstances:
Function is known/required to be an actual function, rather than a global object with an operator() overload. So if a provider of T wants to provide a global functor instead of a regular function (for any number of reasons) this method will not work, even though Function(t) is 100% perfectly valid, legitimate, and does none of those terrible implicit conversions that for some reason must be stopped.
The expression Function(t) is not expected to use ADL to find the actual Function to call.
Function is not a template function.
And not one of these possibilities has anything to do with implicit conversions. If you're going to call Function(t), then it's 100% OK for ADL to find it, template argument deduction to instantiate it, or for the user to fulfill this with some global lambda.
Your second-best bet is to rely on how overload resolution works. C++ only permits a single user-defined conversion in operator overloading. As such, you can create a type which will consume that one user-defined conversion in the function call expression in lieu of T. And that conversion should be a conversion to T itself.
You would use it like this:
template<typename T>
class udc_killer
{
public:
//Will never be called.
operator T const&();
};
template <typename T>
concept has_f = requires () { Function(udc_killer<T>{}); };
This of course still leaves the standard conversions, so you can't differentiate between a function taking a float if T is int, or derived classes from bases. You also can't detect if Function has any default parameters after the first one.
Overall, you're still not detecting the signature, merely call-ability. Because that's all you should care about to begin with.
I've been given a bunch of dummy functions, each one with its own return type, number (and types) of arguments and I'm trying to figure out a way to create function pointers of the correct type to them automatically, then store them inside a map to be retrieved at will. In a nutshell, I'm stuck at creating the actual function pointers. The way of storing them in a map is a separate, follow-up question, due to their variable types.
I think that templates are the way to go, and I've tried creating a templated function that returns the appropriately-typed pointer given the address and types of a function. I think it could not be possible though, so any input is appreciated.
Code for the aforementioned function:
template <typename retType, typename ... argTypes> retType makeFuncPtr(void* funcAddr) {
retType (*ptr)(argTypes) = funcAddr;
return ptr;
}
I'm getting an error "Declaration type contains unexpanded parameter pack 'argTypes'". What am I doing wrong and also which is the appropriate return type for this function, as I'm not actually sure about it?
The error you ask about is because in the line:
retType (*ptr)(argTypes) = funcAddr;
there is no ... after argTypes. Note this would not actually fix the situation because a void pointer can not be converted to some other kind of pointer without a cast. And also you could not convert the function pointer to retType.
If the functions have different signatures this is a fairly tricky problem, I suggest you take a look at libffi, the tricky part here is not storing the function pointers (so long as they are not non-static member functions you can simply cast to void * and store that), the tricky part is using the stored pointer value to make a call.
libffi gives you the ability to describe a function's calling convention, return type and expected arguments. You could then write code that compares the arguments you actually received and either convert or produce an error as appropriate. With C++ it would even be possible to produce that description programmatically (your template function would take a function pointer as a parameter then use the parameter pack to map to the libffi argument type values).
Suppose I have this:
void func(WCHAR* pythonStatement) {
// Do something with pythonStatement
}
And I need to convert it to void function(void) like this:
bind(func, TEXT("console.write('test')"))
Now I have struct like this:
typedef void (__cdecl * PFUNCPLUGINCMD)();
struct FuncItem {
PFUNCPLUGINCMD pFunc;
// ...
};
How can I set the pFunc of my struct to bind(func, "something")? Bind returns lambda_functor not a function pointer, so how can I cast this functor to function pointer?
Thanks.
Ended up using the wrapping "solution" (GitHub)
I think that you can't, unless you make the resulting lamba_functor a global variable.
In that case, you could declare a function that invokes it:
void uglyWorkaround() {
globalLambdaFunctor();
}
and set pFunc to uglyWorkaround().
EDIT
Just a sidenote: if you are binding static text to the function call, you may completely omit bind() call and write just:
void wrapper() {
func(TEXT("console.write('test')"));
}
and set pFunc to wrapper().
Bind returns lambda_functor not a function pointer, so how can I cast this functor to function pointer?
I don't think you can. However, off the top of my head, I can think of several alternatives:
Use boost::function<void()> (or std::function() if your compiler supports TR1 or C++11) instead of void (*)().
It has the ability to bind to just about anything with a somewhat compatible signature.
Put the whole code into a template, make PFUNCPLUGINCMD a template parameter, and let function template argument deduction figure out the exact type.
That's a variation on the former, actually, where you would use the result of bind() directly instead of having boost::function abstract away the gory details.
Create a wrapper that calls the functor returned by boost::bind().
A function template might help to let the compiler figure out the exact types and generate a suitable function, although I haven't tried to do that. However, since you cannot use the result of bind() as a template argument, but need to have give the function access to it nevertheless, you will need a global variable for this. (The ability to avoid this is one of the main advantages of function objects, a very versatile of which is std::function.)
Extend your PFUNCPLUGINCMD callback type to support a user-provided parameter. For C callbacks, this usually is a void*. However, if you pass the address of the object returned by bind() to your callback, you would need to convert it into a pointer to the correct type - which, AFAIK, depends on the arguments provided to bind(). In order to avoid that, you'd need to pass something that abstracts away the exact type. Again, std::function comes to the rescue.
The first idea would be the best, but it requires you to be able to change PFUNCPLUGINCMD. The last one might be best when PFUNCPLUGINCMD needs to be compatible with C, as it uses the common C callback idiom.
You can't do this, unless you want to write your own Just-In-Time compiler. Alternatively, if you control the receiving code, then you could use a boost::function<>, which will accept a variety of function types, including pointers and function objects like those produced by boost::bind.