Visual Studio 2010 and std::function - c++

I have this code:
#include <iostream>
#include <functional>
struct A
{
int operator()(int i) const {
std::cout << "F: " << i << std::endl;
return i + 1;
}
};
int main()
{
A a;
std::tr1::function<int(int)> f = std::tr1::ref(a);
std::cout << f(6) << std::endl;
}
The aim is to pass the functor object by a reference_wrapper, in a way to avoid useless copy costructor calls.
I expect the following output:
F: 6
7
It works correctly with GCC >= 4.4.0, Visual Studio 2008 and with boost by substituting std::tr1 namespace with boost. It only doesn't work with the new Visual Studio 2010 both Express Beta 2 and Release Candidate.
Are this new C++ features bugged in vs2010?
Or there is some mistake or misuse in the code?

I think i found the reason. This is what TR1 3.4/2 says about result_of<T(A1, A2, ..., AN)>::type, used in the determination of the return type of reference_wrapper<T>::operator():
The implementation may determine the type member via any means that produces the exact type of the expression f(t1, t2, ..., tN) for the given types. [Note: The intent is that implementations are permitted to use special compiler hooks —end note]
And then paragraph 3:
If F is not a function object defined by the standard library, and if either the implementation cannot determine the type of the expression f(t1, t2, ..., tN) or if the expression is ill-formed, the implementation shall use the following process to determine the type member:
If F is a possibly cv-qualified class type with no member named result_type or if typename F::result_type is not a type:
If N=0 (no arguments), type is void.
If N>0, type is typename F::template result<F(T1, T2,..., TN)>::type
The error message is an artefact of trying these fall-backs. Provide a typedef for result_type to int and it should work, i think. Notice that in C++0x, this is different. It does not rely on result_type or a result template, since it can use decltype.
If with <functional> it fails with MSVC10 in C++0x mode, it smells like a bug, i would say. But maybe someone else knows what's going on. It may (but is not guaranteed to) work with <tr1/functional> in C++0x mode if that header chooses to take the decltype way instead of ::result_type. I would typedef result_type - that way i think it should always work regardless of whether the tr1 header is used or the c++0x header.
Also notice that boost::tr1 says in its documentation that it does not support the function call operator (but it merely supports implicit conversions to T&).

I encounter a similar problem here :
Prevent unnecessary copies of C++ functor objects
To make it compile on MSVC10, I had to derive my function object from std::unary_function.

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.
*/

Unexpected behavior with template type alias in VS2015

The following code compiles with VS15 Community and prints out "Hello".
#include <functional>
#include <iostream>
template<typename T>
using void_template_alias_t = void;
template<typename T>
using Func = std::function<void( T )>;
template<typename T>
using FuncVoid = Func<void_template_alias_t<T>>;
int main()
{
FuncVoid<void> hello = [] { std::cout << "Hello\n"; };
hello();
}
I think this is not allowed to compile.
I was playing around, the code was a bit more complex. I naively expected this to work, but suddenly realized that this code should not compile because you can't make a Func<void> (or am I wrong with this?).
Did I found a magic workaround?
Is this a new behavior from the C++14 standard?
Or is it simply a compiler bug?
Edit: The following more simplified version does not compile.
#include <functional>
#include <iostream>
template<typename T>
using Func = std::function<void( T )>;
int main()
{
Func<void> hello = [] { std::cout << "Hello\n"; };
hello();
}
So why is the code above compiling and working as I first expected?
Is it a correct implementation, if not, how would it look like?
Or is it simply a compiler bug?
That. As mentioned by #T.C., CWG #577 is relevant:
[…] there
was some concern expressed over the treatment of function templates
and member functions of class templates if the C++ rule were changed:
for a template parameter T, would a function taking a single parameter
of type T become a no-parameter function if it were instantiated with
T = void?
This is a justified complaint, but unfortunate for you, member functions/member function templates and type-ids were affected equally by the resolution:
A parameter list consisting of a single unnamed parameter of non-dependent type void is equivalent to the an empty parameter list.
thus both your snippets are ill-formed, as the parameter's type is indeed dependent.
Is it a correct implementation, if not, how would it look like?
There is no correct implementation. If you need a function type with an empty parameter list, you'll have to specify that independent from template parameters.
So why is the code above compiling and working as I first expected?
My best guess: VC++ does the substitution of void_template_alias_t<T> after assuring that the parameter type is not a dependent type "cv void", but before making the "void -> empty list transformation". However, it's often hard to comprehend how VC++ (or any compiler, for that matter) thinks internally.

std::is_convertible inconsistant with std::function

I noticed some strange results with std::is_convertible and std::is_assignable when std::function object and std::bind are involved.
I would assume that when these functions return true, the conversion can be made. Or am I missing something?
The following code prints different results on different compilers, and I would expect it to print 0 since these types cannot be assigned.
#include <type_traits>
#include <functional>
#include <iostream>
int main()
{
std::cout << std::is_convertible<std::function<void(int)>, std::function<void()>>::value << std::endl;
}
It prints 0 on the following compilers:
gcc 4.8 and gcc 4.9
clang 3.4 (but not the one from ubuntu 12.04)
It prints 1 on the following compilers:
gcc 4.7
VC++12 (VS2013)
clang 3.2
Is there any correct answer?
Are these bugs in compilers or am I messing with stuff that is compiler specific?
In C++11, std::function's constructor taking an arbitrary functor type is specified as (quoting N3337 §20.8.11.2.1 [func.wrap.func.con]/p7):
template<class F> function(F f);
template <class F, class A> function(allocator_arg_t, const A& a, F f);
7 Requires: F shall be CopyConstructible. f shall be Callable (20.8.11.2) for argument types ArgTypes and return type R. The
copy constructor and destructor of A shall not throw exceptions.
Violation of a Requires clause (passing an f not Callable for argument types ArgTypes and return type R) is undefined behavior, so the library is free to do whatever it wants in that case. The library may take the constructor out of overload resolution, but it doesn't have to, and if it doesn't, then you will have issues with overload resolution and std::is_convertible- it will report that pretty much everything under the sun is convertible to std::function (including stuff like double!).
Hence, in LWG issue 2132, the standard was modified to require implementations to remove these constructors from overload resolution (via SFINAE or a similar technique) if the functor isn't Callable for the specified argument types and return type. It now reads:
template<class F> function(F f);
template <class F, class A> function(allocator_arg_t, const A& a, F f);
7 Requires: F shall be CopyConstructible.
8 Remarks: These constructors shall not participate in overload
resolution unless f is Callable (20.9.11.2) for argument types
ArgTypes... and return type R.
So if your standard library implements this resolution, then std::is_convertible<std::function<void(int)>, std::function<void()>>::value is false. Otherwise, it's implementation-dependent.
I would assume that when these functions return true, the conversion can be made. Or am I missing something?
Type traits such as std::is_convertible, std::is_constructible, or std::is_assignable only considers the immediate context - i.e., whether there's a matching function signature that's accessible and not deleted. They don't check if the function's body would compile when instantiated.

Is there a way of implementing the auto keyword for C++03

In C++03 or earlier, is there a way of implementing the auto keyword? Not an object class, but so that it can be used like this [C++11]
auto x = 5;
std::cout << x;
I quickly 'whipped up' an implementation, but it is pretty rubbish, as you can cast it to any type - too much like an object class, and pretty basic, I know, but anyway, here it is:
class auto_t
{
public:
template < typename _Ty > auto_t(const _Ty &_Value)
: __data(_Value)
{
}
template < typename _Ty > operator _Ty()
{
return (_Ty)__data;
}
private:
void *__data;
};
#define auto auto_t
Not really. That's why C++11 introduces it as a keyword, and not a library feature.
There is no way to emulate the C++11 auto functionality with the same syntax. The code you supplied introduces a new type that just attempts to wrap your original type (ignoring the fact that it doesn't actually retain the the original object's lifetime). However, this new type will not follow the same rules for argument dependent lookup and type conversions as your original type. The auto keyword in C++11 is a language feature not a library extension. The best you could do to emulate it is with a MACRO like the boost library does.
I cannot think of any way doing what you want other than writing a compiler that inspects the intended type and creates the appropriate code for you.
That is a language feature and hence implemented by compilers.

A lambda's return type can be deduced by the return value, so why can't a function's?

#include <iostream>
int main(){
auto lambda = [] {
return 7;
};
std::cout << lambda() << '\n';
}
This program compiles and prints 7.
The return type of the lambda is deduced to the integer type based on the return value of 7.
Why isn't this possible with ordinary functions?
#include <iostream>
auto function(){
return 42;
}
int main(){
std::cout << function() << '\n';
}
error: ‘function’ function uses ‘auto’ type specifier without trailing return type
C++14 has this feature. You can test it with new versions of GCC or clang by setting the -std=c++1y flag.
Live example
In addition to that, in C++14 you can also use decltype(auto) (which mirrors decltype(auto) as that of variables) for your function to deduce its return value using decltype semantics.
An example would be that for forwarding functions, for which decltype(auto) is particularly useful:
template<typename function_type, typename... arg_types>
decltype(auto) do_nothing_but_forward(function_type func, arg_types&&... args) {
return func(std::forward<arg_types>(args)...);
}
With the use of decltype(auto), you mimic the actual return type of func when called with the specified arguments. There's no more duplication of code in the trailing return type which is very frustrating and error-prone in C++11.
This is just a limitation of how the language was created and has evolved. In the upcoming C++14 standard the return type of a function can be deduced in some contexts, although not in all. There are complications when there are multiple return statements.
Additionally, deduced return types have other issues, for example, the return type of a template function cannot be used in a SFINAE context, as to be able to deduce the type, the compiler must instantiate the function template, which happens after substitution. The net result is that while the feature will be there in the near future, I would avoid it if you can provide the type yourself.
This is coming in c++14. See the following proposal.
Its not there still.. its gonna be in C++1y/C++14.. check out this link of feature
My guess is that it's probably because type-inferred lambdas can't be recursive.
Why does this matter? Because if a type-inferred lambda could be recursive (by "type-inferred" I mean where the variable's name is of type auto), then its return type could potentially depend on itself -- and while this is sometimes possible to solve, it much more difficult to implement than "simple" type inference. I'm not even sure if it's always solvable (is it decidable in the general case?). If functions supported type inference, though, this issue would have to be taken care of, so it's likely that they just excluded them for this reason.