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.
Related
There are two standard methods of passing arguments -- by value, and constant reference. Each has its trade-offs, with value being preferable in most cases that the data is very small. However, I just recently looked into templates more, and the way I understand it, they act more like a macro. Could you use templates to favor efficiency (disregarding bad code cleanliness for now)? For example, if I passed a std::vector through a template, would it allow access to the current scope to the function called?
I think you are misunderstanding what templates are.
Template arguments are not another way of passing runtime arguments to a function. Templates are a way essentially of doing code generation if you want to use the exact same code multiple times but with different types and/or constants when you know all the types and constant values at compile time.
So to answer your question
For example, if I passed a std::vector through a template, would it
allow access to the current scope to the function called?
you can't pass an std::vector value to a template function beyond normal argument passing which may be parametrized on the type. As for allowing access to a vector in the current scope, you don't need templates for that anyway: pass a reference to the vector.
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.
In a template I have some functions which are only valid for certain template types. GCC seems to be happy with this, but I'm not sure it is valid. Unlike typical SFINAE the function itself is not a template.
template<typename T>
struct generic {
T item;
void get_limited() {
item.limited();
}
};
Provided I don't call get_limited, is it okay to instantiate this class with a type that does not implement limited?
If no, how can I solve this? I have a generic container class where certain features are enabled based on the allocate it is storing (so not directly on the type as above, but still a template parameter).
Template functions are instantiated on demand, so if there is no use of the function it need not be correct, at least for some possible instantiations. The standard does state that if a template is not valid for any instantiating type, the program is ill-formed (although the compiler is not required to diagnose it) even if it is never instantiated.
This feature is used in the standard library in different parts, where the requirements of a single function might be stricter than the general requirements that the template places on the instantiating types. For example, in the case of std::map, in general, the value type does not need to be default constructible, but if you want to use operator[] then it needs to be, since that operator might need to create an empty element if the key is not present.
I have a library where template classes/functions often access explicit members of the input type, like this:
template <
typename InputType>
bool IsSomethingTrue(
InputType arg1) {
typename InputType::SubType1::SubType2 &a;
//Do something
}
Here, SubType1 and SubType2 are themselves generic types that were used to instantiate InputType. Is there a way to quickly find all the types in the library that are valid to pass in for InputType (likewise for SubType1 and SubType2)? So far I have just been searching the entire code base for classes containing the appropriate members, but the template input names are reused in a lot of places so it is very cumbersome.
From a coding perspective, what is the point of using a template like this when there is only a limited set of valid input types that are probably already defined? Why not just overload this function with explicit types rather than making them generic?
From a coding perspective, what is the point of using a template like this when there is only a limited set of valid input types that are probably already defined? Why not just overload this function with explicit types rather than making them generic?
First of all, because those overload would have the exact same body, or very similar ones. If the body of the function is long enough, having more versions of it is a problem for maintenance. When you need to change the algorithm, you now have to do it N times and hope you won't make mistakes. Most of the times, redundancy is bad.
Moreover, even though now there could be just a few such types which satisfy the syntactic requirements of your function, there may be more in future. Having a function template allows you to let your algorithm work with new types without the need to write a new overload every time one new such type is introduced.
The advantage of using generic types is not on the template end: if you're willing to explicitly name them and edit the template code every time, it's the same.
What happens, however, when you introduce a subclass or variant of a type accepted by the template? No modification needed on the other end.
In other words, when you say that all types are known beforehand, you are excluding code modifications and extensions, which is half the point of using templates.
In my code I'm adopting a design strategy which is similar to some standard library algorithms in that the exact behavior can be customized by a function object. The simplest example is std::sort, where a function object can control how the comparison is made between objects.
I notice that the Visual C++ provides two implementations of std::sort, which naturally involves code duplication. I would have imagined that it was instead possible to have only one implementation, and provide a default comparator (using operator< ) as a default template parameter.
What is the rational behind two separate versions? Would my suggestion make the interface more complex in some way? Or result in confusing error messages when the object does not provide operator< ? Or maybe it just doesn't work?
Thanks,
David
Because function templates are not allowed by the standard to have default type arguments.
This, however, was amended in C++11, and now function templates can have default type arguments.
Prior to C++11, a function template could not have default template arguments, and a template argument cannot be deduced from a default function argument, so there was no way to make this work.
In C++11, which supports default template arguments for function templates, you could use a single function template, but changing it now would break backwards compatibility with older C++ code that relies on the functions having a particular type.