Why there is no std::make_raw_storage_iterator? - c++

I'm wondering why std::raw_storage_iterator does not have an accompanying std::make_raw_storage_iterator like std::move_iterator and std::make_move_iterator. The std::raw_storage_iterator class template has two template parameters. So I think it is actually more useful to provide a make function for std::raw_storage_iterator than std::move_iterator which only has a single template parameter to specify.

With #dyps suggestions, a sensible implementation is indeed possible:
template <typename OutputIt>
auto make_raw_storage_iterator( OutputIt out ) {
return std::raw_storage_iterator<OutputIt, std::remove_pointer_t<decltype(&*out)>>(out);
}
(Demo with cppreference's example)
This is guaranteed to work since ยง20.7.10/1, which imposes requirements for the template arguments of raw_storage_iterator, mandates that:
OutputIterator is required to have its operator* return an object for
which operator& is defined and returns a pointer to T [..]
Where T is the second argument, the value type of the output range. So, given the underlying output iterator, we have enough information to determine the intended specialization of raw_storage_iterator.
The reason this has not been proposed is assuredly not more than an oversight - consider that make_reverse_iterator or even make_unique have not been provided before C++14, either. Feel free to take the first step.

Related

How can I check that assignment of const_reverse_iterator to reverse_iterator is invalid?

Consider the following:
using vector_type = std::vector<int>;
using const_iterator = typename vector_type::const_iterator;
using const_reverse_iterator = typename vector_type::const_reverse_iterator;
using iterator = typename vector_type::iterator;
using reverse_iterator = typename vector_type::reverse_iterator;
int main()
{
static_assert(!std::is_assignable_v<iterator, const_iterator>); // passes
static_assert(!std::is_assignable_v<reverse_iterator, const_reverse_iterator>); // fails
static_assert(std::is_assignable_v<reverse_iterator, const_reverse_iterator>); // passes
}
I can check that assignment of iterator{} = const_iterator{} is not valid, but not an assignment of reverse_iterator{} = const_reverse_iterator{} with this type trait.
This behavior is consistent across gcc 9.0.0, clang 8.0.0, and MSVC 19.00.23506
This is unfortunate, because the reality is that reverse_iterator{} = const_reverse_iterator{} doesn't actually compile with any of the above-mentioned compilers.
How can I reliably check such an assignment is invalid?
This behavior of the type trait implies that the expression
std::declval<reverse_iterator>() = std::declval<const_reverse_iterator>()
is well formed according to [meta.unary.prop], and this appears consistent with my own attempts at an is_assignable type trait.
This trait passes because the method exists that can be found via overload resolution and it is not deleted.
Actually calling it fails, because the implementation of the method contains code that isn't legal with those two types.
In C++, you cannot test if instantiating a method will result in a compile error, you can only test for the equivalent of overload resolution finding a solution.
The C++ language and standard library originally relied heavily on "well, the method body is only compiled in a template if called, so if the body is invalid the programmer will be told". More modern C++ (both inside and outside the standard library) uses SFINAE and other techniques to make a method "not participate in overload resolution" when its body would not compile.
The constructor of reverse iterator from other reverse iterators is the old style, and hasn't been updated to "not participate in overload resolution" quality.
From n4713, 27.5.1.3.1 [reverse.iter.cons]/3:
template<class U> constexpr reverse_iterator(const reverse_iterator<U>& u);
Effects: Initializes current with u.current.
Notice no mention of "does not participate in overload resolution" or similar words.
The only way to get a trait you want like this would be to
Change (well, fix) the C++ standard
Special case it
I'll leave 1. as an exercise. For 2., you know that reverse iterators are templates over forward iterators.
template<class...Ts>
struct my_trait:std::is_assignable<Ts...> {};
template<class T0, class T1>
struct my_trait<std::reverse_iterator<T0>, std::reverse_iterator<T1>>:
my_trait<T0, T1>
{};
and now my_trait is is_assignable except on reverse iterators, where it instead tests assignability of the contained iterators.
(As extra fun, a reverse reverse iterator will work with this trait).
I once had to do something very similar with std::vector<T>::operator<, which also blindly called T<T and didn't SFINAE disable it if that wasn't legal.
It may also be the case that a C++ standard library implementation can make a constructor which would not compile not participate in overload resolution. This change could break otherwise well formed programs, but only by things as ridiculous as your static assert (which would flip) or things logically equivalent.
It's just a question of constraints. Or lack thereof. Here's a reduced example with a different trait:
struct X {
template <typename T>
X(T v) : i(v) { }
int i;
};
static_assert(is_constructible_v<X, std::string>); // passes
X x("hello"s); // fails
Whenever people talk about being SFINAE-friendly - this is fundamentally what they're referring to. Ensuring that type traits give the correct answer. Here, X claims to be constructible from anything - but really it's not. is_constructible doesn't actually instantiate the entire construction, it just checks the expression validity - it's just a surface-level check. This is the problem that enable_if and later Concepts are intended to solve.
For libstdc++ specifically, we have:
template<typename _Iter>
_GLIBCXX17_CONSTEXPR
reverse_iterator(const reverse_iterator<_Iter>& __x)
: current(__x.base()) { }
There's no constraint on _Iter here, so is_constructible_v<reverse_iterator<T>, reverse_iterator<U>> is true for all pairs T, U, even if it's not actually constructible. The question uses assignable, but in this case, assignment would go through this constructor template, which is why I'm talking about construction.
Note that this is arguably a libstdc++ bug, and probably an oversight. There's even a comment that this should be constrained:
/**
* A %reverse_iterator across other types can be copied if the
* underlying %iterator can be converted to the type of #c current.
*/

Is it good practice to require the type in a class template to respond to a certain func?

The std lib has types in class templates that requires the type to override certain OPERATORS, for exmple, the type we use in std::map requires the type to support the < operator.
But is it good to require certain FUNCTIONS? Consider this silly example
template <typename T> struct Foo {
T t;
Foo() {
t.push_back(0);
}
};
int main() {
Foo<std::vector<int>> foo;
return 0;
}
there i've created a class template Foo and it's type needs to have a push_back member func. Is this design acceptable/common to c++ coders?
What you're describing is called a template policy (see this) and it's a perfectly legitimate and common design pattern for classes or functions.
Sure. Just document the requirements on template parameters when describing the class template.
Note that in your example, T actually only needs a push_back function if the default constructor Foo<T>() is used. (As far as the language is concerned. Your requirements could be stricter to be on the safe side.)
If you're using a recent compiler, you can also use static_assert to make sure most template parameter requirements are obeyed, and/or to make the error messages when a requirement is disobeyed more legible.
Yes, it's fine. The standard does it all the time. As an example, consider std::back_inserter which, as your example does, presumes that its template type implements a push_back member function. While we still don't have concepts though, you had better document your requirements. It also helps to name your template types in a meaningful way; so instead of template <typename T>, you might have template <typename Container>.

Can enable_if be used as a non-extra parameter (e.g. for a constructor)?

I am writing a new container, and trying to comply with N3485 23.2.3 [sequence.reqmts]/14, which states:
For every sequence container defined in this Clause and in Clause 21:
If the constructor
template <class InputIterator>
X(InputIterator first, InputIterator last,
const allocator_type& alloc = allocator_type())
is called with a type InputIterator that does not qualify as an
input iterator, then the constructor shall not participate in overload
resolution.
(/14 repeats this almost verbatim for the member functions taking iterator ranges)
N3485 23.2.3 [sequence.reqmts]/15 says:
The extent to which an implementation determines that a type cannot be an input iterator is unspecified, except that as a minimum integral types shall not qualify as input iterators.
My understanding is that the phrase "shall not participate in overload resolution" means that the container implementer is supposed to use SFINAE tricks to disable that constructor or member function during template argument deduction. For the member functions, this is no big deal; as the return type on a function is the normal way to use enable_if. But for the constructor, there is no return type on which enable_if can be applied. This was my first attempt to declare the constructor:
// The enable_if use below is to comply with 23.2.3 [sequence.reqmts]/14:
// ... is called with a type InputIterator that does not qualify as an input iterator
// then the constructor shall not participate in overload resolution.
template <typename InputIterator>
path(std::enable_if<!std::is_integral<InputIterator>::value, InputIterator>::type first,
InputIterator last, Allocator const& allocator = allocator_type());
However, boost's enable_if docs suggest using a dummy pointer parameter initialized to nullptr instead of using an actual parameter to a function. Is that necessary for correct behavior here or is the preceding declaration of path's iterator range constructor okay?
The Good Robot (R. Martinho Fernandes) discusses the issue with a clean C++11 solution, namely using a default template parameter to apply enable_if, in his blog.
However, let me just point out here that doing
template< class Type >
void foo( typename Something< Type >::T )
foils argument deduction.
It's still possible to call the function, by explicitly providing the template argument. But in C++ the compiler will simply refuse to match e.g. a MyType actual argument to formal argument type Something<Blah>::T, because while this can be done in some special cases it cannot always be done (there could be countless choices of Blah where Something<Blah>::T was MyType).
So, your current approach won't work in general, but the whole problem of the specification's requirement is a C++11 problem, so the C++11 specific solution is OK! :-)

Can it cause problems to explicitly pass a reference into a function template that's not expecting one?

There was a question regarding passing taking the following function template, and instantiating it with a by-reference string parameter:
template <typename T>
void foo(T t) {}
The answer was, of course, to give the argument explicitly:
int main() {
std::string str("some huge text");
foo<std::string&>(str);
}
(As an aside, there was a suggestion about using deduction and passing C++0x's std::ref(str), but this requires the use of .get() inside the function, and the OP's requirement was transparency.)
However, IMO there can be little doubt that the author of the function template intended for the argument to be passed by value, or he would have written:
template <typename T>
void foo(T& t) {}
(It's possible that he deliberately intended for either to be possible, but this seems unlikely to me for some reason.)
Are there any "reasonable" scenarios where passing a reference into foo<T>, where the author of foo had intended the function always to take its argument by value, may cause problems?
The answer I'm looking for most likely consists of a function body for foo, where the use of a reference type for T leads to unexpected/undesirable semantics when compared to the use of a value type for T.
Consider that it's common to write algorithms like this:
template <typename InputIterator>
void dosomething(InputIterator first, InputIterator last, otherparams) {
while (first != last) {
do the work;
++first;
}
}
It's also how the standard algorithms are implemented both in GCC and in the old SGI STL.
If first is taken by reference then it will be modified, so certainly there are plenty of template functions out there that will "go wrong" with reference template arguments. In this example, first is changed to a value equal to last. In another implementation, or in the next release, it might be copied and not modified at all. That's "unexpected/undesirable semantics".
Whether you call this a "problem" or not, I'm not sure. It's not the behavior that the author of the function intended, and it's probably not documented what happens to first if it's passed by reference (it isn't for the standard algorithms).
For the standard algorithms I think it's UB, so the caller is at fault. The standard says that the template argument should be an iterator, and while T* or some library iterator is an iterator type, T* & or reference-to-library-iterator isn't.
As long as authors of template functions have documented the requirements of their template arguments clearly, I suspect that typically it will just fall out in the same way as for standard algorithms and iterators -- reference types are not valid template arguments, and hence the caller is at fault. In cases where the requirements are very simple (a couple of expressions with specified behavior), a reference type probably isn't ruled out, but again as long as the function doesn't say that it doesn't modify the argument, and doesn't say how it modifies the argument, callers should consider that since it's not documented how the argument is modified, then it's unspecified. If they call the function with a reference type, and get surprised whether or how the argument is modified, again it's the caller's fault.
I expect that under-documented functions are at risk of a dispute whose fault it is when it goes wrong, though, since sometimes it'll rely on quite a close reading.
If the programmer decided to be lazy, and use the input parameter as a temporary variable to calculate the output, then you would get problematic results:
template <class T>
T power2n(T a, int n) {
if (n == 0) return 1;
for (int i = 0 ; i < n; i++)
{
a *= a;
}
return a;
}
Now if I pass the first parameter by reference, its value gets messed up.
Not saying this is good programming, just saying it happens.

Why doesn't unary_function define operator()?

I was just looking for a handy base class for a set of functors to be based on taking and int and returning void.
Thinking to use std/functional the functors are basically going to be unary_function<int,void> with operator().
Why is virtual result_type operator()(const argument_type& _Left) const = 0; not defined on the unary_function template? I'm guessing that it's because there could be variations in constness...
Is there some other template I've missed that includes the operator()?
I haven't done this in a while, am I missing something?
How would I also make use of existing functional like
std::ptr_fun< HWND, void >(someFunction);
std::pointer_to_unary_function<HWND, void>(someFunction);
EDIT:
Perhaps I should include the other half of the usage to make this complete. Maybe it's the usage half that is not fitting in with the concept.
How would one pass the functor to a method and use it?
typedef unary_function<int,void> Functor;
void DoStuff(const Functor& functor) {
int demo = 1;
functor(demo);
}
functor as a unary_function doesn't define operator() and so DoStuff doesn't compile.
Template concepts are duck-typed. The fact that a class satisfying the UnaryFunction concept needs operator() is specified in the documentation and inferred from the templates which use template parameters satisfying that concept. There's no need to spell out the function signature, or to require that it be virtual, that it take a const reference parameter, or that it be a const member function.
The unary_function template should not be thought of as an interface (and it isn't designed as one). It's certainly not a polymorphic base class. It's a helper, which is used by classes that wish to implement the AdaptableUnaryFunction concept.
From the STL docs, which are reliable for the original design rationale: "the only reason it exists is to make defining Adaptable Unary Functions more convenient" - http://www.sgi.com/tech/stl/unary_function.html
The standard is similar: "The following classes are provided to simplify the typedefs of the argument and result types" (20.3.1/1)
Advanced usage - actually what's required for UnaryFunction is that if f is a unary function object, and x is convertible to the argument type, then f(x) is a valid expression of the result type. It needn't have a one-argument operator() at all, it's fine to have a two-arg operator() with the second arg having a default value. Try defining that as a pure virtual function ;-)
Second question, you make use of ptr_fun just by calling it with function name/pointer. Its template parameters will be inferred from the function type, so you don't need to specify them. The result is an object of the corresponding pointer_to_unary_function template type.
To use the example straight from the STL docs:
transform(first, last, first,
compose1(negate<double>, ptr_fun(fabs)));
This is approximately equivalent to:
for (auto current = first; current != last; ++current) {
*current = -fabs(*current);
}
(where I use auto in its C++0x sense, meaning "I cannot be bothered / it is impossible to write the iterator type here")
A function name/pointer can be used in transform (which takes a UnaryFunction template parameter), but not in compose1 (which takes an AdapatableUnaryFunction template parameter). So without ptr_fun, there's no way to compose negate with fabs.
In response to your Edit, I stress, unary_function is not a polymorphic base class. You cannot usefully use it (or any of its instantiations) as a function parameter type.
If you want to use the UnaryFunction or AdaptableUnaryFunction concepts, then you must write a function template:
template <typename UnaryFunction>
void DoStuff(UnaryFunction &functor) {
int demo = 1;
functor(demo);
}
This only requires that the functor take a type which int converts to, though. It doesn't require that it take exactly int and return exactly void. That's usually an advantage.
If a template doesn't do what you want, then unary_function is not for you. You haven't missed anything: you can design your own interface with a virtual operator(), but the standard libraries don't aim to provide any such thing.
Because a virtual operator () is not a part of the unary_function concept. The unary function concept can have a non-virtual operator in addition to differences in constness.