For C++ templates, is there a way find types that are "valid" inputs? - c++

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.

Related

Check existence of (global) function but disallow implicit conversion

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.

c++ auto for type and nontype templates

In c++17 template <auto> allows to declare templates with arbitrary type parameters. Partially inspired by this question, it would be useful to have an extension of template <auto> that captures both type and nontype template parameters, and also allows for a variadic version of it.
Are there plans for such an extension in the next c++20 release? Is there some fundamental problem in having a syntax like template<auto... X>, with X any type or nontype template parameter?
Are there plans for such an extension in the next c++20 release?
No.
Is there some fundamental problem in having a syntax like template<auto... X>, with X any type or nontype template parameter?
It would be a totally new concept in the language - having a name refer to either a type or a value in the same place. So it'd come with all sorts of additional questions - and probably additional language features to check if X is a type or not.
The syntax likely cannot be template <auto... X> struct Y { }; since that syntax already has meaning and means a bunch of values and Y<int>{} is ill-formed.
There are definitely places where such a thing would be useful though. A proposal would just have to address these issues.
The big issue with trying to do something like that is grammar. Template parameters state up-front whether they are templates, types, or values, and the most important reason for this is grammatical.
C++ is a context-sensitive grammar. That means that you cannot know, just from a sequence of tokens, what a particular sequence of tokens means. For example, IDENTIFIER LEFT_PAREN RIGHT_PAREN SEMICOLON. What does that mean?
It could mean to call a function named by IDENTIFIER with no parameters. It could mean to default initialize a prvalue of a class named by IDENTIFIER. These are rather different things; you might conceptually see them as similar, but C++'s grammar does not.
Templates are not macros; they're not doing token pasting. There is some understanding that a piece of code in a template is supposed to mean a specific thing. And you can only do that if you at least know what kind of thing a template parameter is.
In order to retain this ability, these "omni template parameters" cannot be utilized until you actually know what they mean. So in order to create such a feature in C++, you would need to:
Create a new syntax to declare omni template parameters (auto isn't going to fly, as it already has a specific meaning).
Provide a syntax for determining what kind of thing an omni template parameter is.
Require the user to invoke that syntax before they can use such parameter names in most ways. This would typically be via some form of specialized if constexpr block, but pattern matching proposals represent an interesting alternative/additional way to handle them (since they can be expressions as well as statements). And expansion statements represent a possible way to access all of the omni parameters in a parameter pack.
I can't see how it would be useful that a template argument could be dynamically either a type or a value? The code statements that use types are very different to those that which use constant values introduced through the template argument.
The only way would be a big "if constexpr" which would make it pointless in my view.
Ok, having looked more closely at the referenced question, I guess there is room there for generically pass-through wrapping the various explicit base template implementations that use different parameter orderings. I still fail to see a huge benefit. The compiler errors when it goes wrong are going to be unfathomable, if nothing else!
I remember being told that overloading and templates were going to rid the world of the unfathomable error messages generated from macros. I have yet to see it!

Method operating on container: hardcode the container type, or use generic template iterators?

I have code where, conceptually, my input is some container of Foo objects. The code "processes" these objects one by one, and the desired result is to fill up a container of FooProduct result objects.
I only need a single pass through the input container. The "processing" is stateful (this isn't an std::transform()) and the number of result objects is independent of the number of input objects.
Offhand, I could see two obvious ways to define the API here.
The easiest way to do this is to hardcode a specific type of container. For example, I could decide I'm expecting vector parameters, e.g.:
void ProcessContainerOfFoos(const std::vector<Foo>& in, std::vector<FooProduct>&out);
But, I don't really have any reason to limit client code to a particular type of container. Instead of constraining the parameter types specifically to vector, I could make the method generic and use iterators as template parameters:
/**
* #tparam Foo_InputIterator_T An input iterator giving objects of type Foo.
* #tparam FooProduct_OutputIterator_T An output iterator writing objects
* of type FooProduct.
*/
template<typename Foo_InputIterator_T, typename FooProduct_OutputIterator_T >
void ProcessContainerOfFoos(Foo_InputIterator_T first, Foo_InputIterator_T last,
FooProduct_OutputIterator_T out);
I'm debating between these two formulations.
Considerations
To me, the first code seems to me to be "easier" and the second seems "more correct":
Non-template types make the signature clearer; I don't need to explain in the documentation what types to use and what the constraints on the template parameter are.
Without templates I can hide the implementation in the .cpp file; with templates I'll need to expose the implementation in a header file, forcing client code to include anything I need for the actual processing logic.
The templated version feels like it expresses my intention more clearly, because I'd rather be indifferent to what container type is used.
The templated version is more flexible and testable - for example, in my code I might be using some custom data structure MySuperEfficientVector , but I'd still be able to test MyFooProcessor without any dependency on the custom class.
Beyond subjective choice given these considerations, is there a major reason to choose one of these over the other? Likewise, is there a better way to construct this API which I'm missing?
Besides the considerations that you've already listed:
The template version allows the client code to pass any iterator
range, for example a sub-range or reverse iterators, not just an entire container from begin to end.
The template version allows passing value types other than Foo. For this to be useful, the processing must be generic of course.
If the template works with only specific value type and the user tries to use iterators to wrong type, the error message might not be very descriptive of their mistake. If this is a concern, you can give the user a better error using type traits: static_assert(std::is_same<Iter::value_type, Foo>::value, "I want my Foo"); Until concepts proposal is added to the standard, there is no good way to communicate the requirements of a template type in the signature to the user.
There is also the option to provide both functions. The hard coded one can delegate to the templated version. This gives you the advantages of both versions at the expense of bloating your api.
It depends. If this function is going to be used with vectors for the time beeing why bother?
I suggest doing templated version only when it becomes necessary. Predicting such things in advance is hard.

Specializing std::optional

Will it be possible to specialize std::optional for user-defined types? If not, is it too late to propose this to the standard?
My use case for this is an integer-like class that represents a value within a range. For instance, you could have an integer that lies somewhere in the range [0, 10]. Many of my applications are sensitive to even a single byte of overhead, so I would be unable to use a non-specialized std::optional due to the extra bool. However, a specialization for std::optional would be trivial for an integer that has a range smaller than its underlying type. We could simply store the value 11 in my example. This should provide no space or time overhead over a non-optional value.
Am I allowed to create this specialization in namespace std?
The general rule in 17.6.4.2.1 [namespace.std]/1 applies:
A program may add a template specialization for any standard library template to namespace std only if the declaration depends on a user-defined type and the specialization meets the standard library requirements for the original template and is not explicitly
prohibited.
So I would say it's allowed.
N.B. optional will not be part of the C++14 standard, it will be included in a separate Technical Specification on library fundamentals, so there is time to change the rule if my interpretation is wrong.
If you are after a library that efficiently packs the value and the "no-value" flag into one memory location, I recommend looking at compact_optional. It does exactly this.
It does not specialize boost::optional or std::experimental::optional but it can wrap them inside, giving you a uniform interface, with optimizations where possible and a fallback to 'classical' optional where needed.
I've asked about the same thing, regarding specializing optional<bool> and optional<tribool> among other examples, to only use one byte. While the "legality" of doing such things was not under discussion, I do think that one should not, in theory, be allowed to specialize optional<T> in contrast to eg.: hash (which is explicitly allowed).
I don't have the logs with me but part of the rationale is that the interface treats access to the data as access to a pointer or reference, meaning that if you use a different data structure in the internals, some of the invariants of access might change; not to mention providing the interface with access to the data might require something like reinterpret_cast<(some_reference_type)>. Using a uint8_t to store a optional-bool, for example, would impose several extra requirements on the interface of optional<bool> that are different to the ones of optional<T>. What should the return type of operator* be, for example?
Basically, I'm guessing the idea is to avoid the whole vector<bool> fiasco again.
In your example, it might not be too bad, as the access type is still your_integer_type& (or pointer). But in that case, simply designing your integer type to allow for a "zombie" or "undetermined" value instead of relying on optional<> to do the job for you, with its extra overhead and requirements, might be the safest choice.
Make it easy to opt-in to space savings
I have decided that this is a useful thing to do, but a full specialization is a little more work than necessary (for instance, getting operator= correct).
I have posted on the Boost mailing list a way to simplify the task of specializing, especially when you only want to specialize some instantiations of a class template.
http://boost.2283326.n4.nabble.com/optional-Specializing-optional-to-save-space-td4680362.html
My current interface involves a special tag type used to 'unlock' access to particular functions. I have creatively named this type optional_tag. Only optional can construct an optional_tag. For a type to opt-in to a space-efficient representation, it needs the following member functions:
T(optional_tag) constructs an uninitialized value
initialize(optional_tag, Args && ...) constructs an object when there may be one in existence already
uninitialize(optional_tag) destroys the contained object
is_initialized(optional_tag) checks whether the object is currently in an initialized state
By always requiring the optional_tag parameter, we do not limit any function signatures. This is why, for instance, we cannot use operator bool() as the test, because the type may want that operator for other reasons.
An advantage of this over some other possible methods of implementing it is that you can make it work with any type that can naturally support such a state. It does not add any requirements such as having a move constructor.
You can see a full code implementation of the idea at
https://bitbucket.org/davidstone/bounded_integer/src/8c5e7567f0d8b3a04cc98142060a020b58b2a00f/bounded_integer/detail/optional/optional.hpp?at=default&fileviewer=file-view-default
and for a class using the specialization:
https://bitbucket.org/davidstone/bounded_integer/src/8c5e7567f0d8b3a04cc98142060a020b58b2a00f/bounded_integer/detail/class.hpp?at=default&fileviewer=file-view-default
(lines 220 through 242)
An alternative approach
This is in contrast to my previous implementation, which required users to specialize a class template. You can see the old version here:
https://bitbucket.org/davidstone/bounded_integer/src/2defec41add2079ba023c2c6d118ed8a274423c8/bounded_integer/detail/optional/optional.hpp
and
https://bitbucket.org/davidstone/bounded_integer/src/2defec41add2079ba023c2c6d118ed8a274423c8/bounded_integer/detail/optional/specialization.hpp
The problem with this approach is that it is simply more work for the user. Rather than adding four member functions, the user must go into a new namespace and specialize a template.
In practice, all specializations would have an in_place_t constructor that forwards all arguments to the underlying type. The optional_tag approach, on the other hand, can just use the underlying type's constructors directly.
In the specialize optional_storage approach, the user also has the responsibility of adding proper reference-qualified overloads of a value function. In the optional_tag approach, we already have the value so we do not have to pull it out.
optional_storage also required standardizing as part of the interface of optional two helper classes, only one of which the user is supposed to specialize (and sometimes delegate their specialization to the other).
The difference between this and compact_optional
compact_optional is a way of saying "Treat this special sentinel value as the type being not present, almost like a NaN". It requires the user to know that the type they are working with has some special sentinel. An easily specializable optional is a way of saying "My type does not need extra space to store the not present state, but that state is not a normal value." It does not require anyone to know about the optimization to take advantage of it; everyone who uses the type gets it for free.
The future
My goal is to get this first into boost::optional, and then part of the std::optional proposal. Until then, you can always use bounded::optional, although it has a few other (intentional) interface differences.
I don't see how allowing or not allowing some particular bit pattern to represent the unengaged state falls under anything the standard covers.
If you were trying to convince a library vendor to do this, it would require an implementation, exhaustive tests to show you haven't inadvertently blown any of the requirements of optional (or accidentally invoked undefined behavior) and extensive benchmarking to show this makes a notable difference in real world (and not just contrived) situations.
Of course, you can do whatever you want to your own code.

C++ Template Specialization Compilation

I'm going to outline my problem in detail to explain what I'm trying to achieve, the question is in the last paragraph if you wish to ignore the details of my problem.
I have a problem with a class design in which I wish to pass a value of any type into push() and pop() functions which will convert the value passed into a string representation that will be appended to a string inside the class, effectively creating a stream of data. The reverse will occur for pop(), taking the stream and converting several bytes at the front of the stream back into a specified type.
Making push() and pop() templates tied with stringstream is an obvious solution. However, I wish to use this functionality inside a DLL in which I can change the way the string is stored (encryption or compression, for example) without recompilation of clients. A template of type T would need to be recompiled if the algorithm changes.
My next idea was to just use functions such as pushByte(), pushInt(), popByte(), popInt() etc. This would allow me to change the implementation without recompilation of clients, since they rely only on a static interface. This would be fine. However, it isn't so flexible. If a value was changed from a byte to a short, for example, all instances of pushByte() corresponding to that value would need to be changed to pushShort(), similarly for popByte() to popShort(). Overloading pop() and push() to combat this would cause conflictions in types (causing explicit casting, which would end up causing the same problem anyway).
With the above ideas, I could create a working class. However, I wondered how specialized templates are compiled. If I created push<byte>() and push<short>(), it would be a type specific overload, and the change from byte to short would automatically switch the template used, which would be ideal.
Now, my question is, if I used specialized templates only to simulate this kind of overloading (without a template of type T), would all specializations compile into my DLL allowing me to dispatch a new implementation without client recompilation? Or are specialized templates selected or dropped in the same way as a template of type T at client compilation time?
First of all, you can't just have specialized templates without a base template to specialize. It's just not allowed. You have to start with a template, then you can provide specializations of it.
You can explicitly instantiate a template over an arbitrary set of types, and have all those instantiations compiled into your DLL, but I'm not sure this will really accomplish much for you. Ultimately, templates are basically a compile-time form of polymorphism, and you seem to need (at least a limited form of) run-time polymorphism.
I'd probably just use overloading. The problem that I'd guess you're talking about arises with something on the order of:
int a;
byte b;
a = pop();
b = pop();
Where you'd basically just be overloading pop on the return type (which, as we all know, isn't allowed). I'd avoid that pretty simply -- instead of returning the value, pass a reference to the value to be modified:
int a;
byte b;
pop(a);
pop(b);
This not only lets overload resolution work, but at least to me looks cleaner as well (though maybe I've just written too much assembly language, so I'm accustomed to things like "pop ax").
It sounds like you have 2 opposing factors:
You want your clients to be able to push/pop/etc. every numeric type. Templates seem like a natural solution, but this is at odds with a consistent (only needs to be compiled once) implementation.
You don't want your clients to have to recompile when you change implementation aspects. The pimpl idiom seems like a natural solution, but this is at odds with a generic (works with any type) implementation.
From your description, it sounds like you only care about numeric types, not arbitrary T's. You can declare specializations of your template for each of them explicitly in a header file, and define them in a source file, and clients will use the specializations you've defined rather than compiling their own. The specializations are a form of compile time polymorphism. Now you can combine it with runtime polymorphism -- implement the specializations in terms of an implementation class that is type agnostic. Your implementation class could use boost::variant to do this since you know the range of possible T's ahead of time (boost::variant<int, short, long, ...>). If boost isn't an option for you, you can come up with a similar scheme yourself so long as you have a finite number of Ts you care about.