I have this code:
#include <iostream>
#include <functional>
#include <vector>
int main () {
std::vector<int> kk;
kk.push_back(2);
std::function<int(int)> foo = std::function<int(int)>([kk](int x)
{
kk.push_back(1);
return kk[0]+1;
});
std::cout << "foo: " << foo(100) << '\n';
return 0;
}
Why I cannot modify vector kk, passed via capture, inside lambda function?
I got this error:
11:21: error: passing 'const std::vector' as 'this' argument of
'void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp,
_Alloc>::value_type&&) [with _Tp = int; _Alloc = std::allocator; std::vector<_Tp, _Alloc>::value_type = int]' discards qualifiers
[-fpermissive]
I can pass it by reference, but problem is, that it will go out of scope if my lambda is called from thread and vector will no longer be available.
By default, a closure type declares its operator() as const-qualified member function. Which means objects captured by copy cannot be modified inside the lambda. To make the operator() a non-const member function, you have to mark the lambda mutable:
std::function<int(int)> foo{[kk](int x) mutable
{
kk.push_back(1);
return kk[0]+1;
}};
[Live example]
(I also took the liberty of removing the double type specification in the declaration).
Of course, bear in mind that the copy of kk made in the capture is local to the lambda object. The local variable kk in main will not be modified by calling foo.
Related
I'm having some trouble when using coeffRef() with a CWiseUnaryView function, but only when the function is declared as const
Reproducible example:
#include <Eigen/Core>
struct dummy_Op {
EIGEN_EMPTY_STRUCT_CTOR(dummy_Op)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE const double&
operator()(const double &v) const { return v; }
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE double&
operator()(double &v) const { return v; }
};
void foo(Eigen::MatrixXd &out)
{
//Compiles
Eigen::CwiseUnaryView<dummy_Op, Eigen::MatrixXd> view(out);
view.coeffRef(0,0);
//Doesn't Compile
const Eigen::CwiseUnaryView<dummy_Op, Eigen::MatrixXd> const_view(out);
const_view.coeffRef(0,0);
}
Returns:
<source>: In function 'void foo(Eigen::MatrixXd&)':
<source>:21:28: error: passing 'const Eigen::CwiseUnaryView<dummy_Op,
Eigen::Matrix<double, -1, -1> >' as 'this' argument discards qualifiers
[-fpermissive]
const_view.coeffRef(0,0);
^
In file included from /opt/compiler-explorer/libs/eigen/v3.3.4/Eigen/Core:413,
from <source>:1:
/opt/compiler-explorer/libs/eigen/v3.3.4/Eigen/src/Core/DenseCoeffsBase.h:340:33: note:
in call to 'Eigen::DenseCoeffsBase<Derived, 1>::Scalar&
Eigen::DenseCoeffsBase<Derived, 1>::coeffRef(Eigen::Index, Eigen::Index)
[with Derived = Eigen::CwiseUnaryView<dummy_Op, Eigen::Matrix<double,
-1, -1> >; Eigen::DenseCoeffsBase<Derived, 1>::Scalar = double; Eigen::Index = long int]'
EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col)
^~~~~~~~
Compiler returned: 1
Compiler explorer: https://godbolt.org/z/kPHPuC
The side-effect of this, is that the multiplication of two (non-const) CWiseUnaryViews also fails, see example here: https://godbolt.org/z/JYQb3d
The bottom line is that you're calling a non-const method of a constant instance. The (first) coeffRef that is being called is the one (and only) in DenseCoeffsBase.h (DenseCoeffsBase<Derived, WriteAccessors>), which is not const qualified. The DenseCoeffsBase<Derived, ReadOnlyAccessors> class does not have a coeffRef method. You can get around this error (and get a warning) if you enable the -fpermissive compiler flag.
In the dense case, you probably want to use the operator()(Index, Index) method anyway, which does have a const qualified version. I just noticed the documentation explicitly says to use that method anyway, even for the non-const version. This is obviously not going to return a const reference, but at least in your example as a double, it shouldn't matter too much.
CwiseUnaryView is intended to be used for L-value like expression, e.g.,
MatrixXcd A;
A.real() = something; // `A.real()` is writable
If you want to apply an element-wise functor and use it as an R-value, you should use CwiseUnaryOp instead:
void foo(Eigen::MatrixXd &out)
{
Eigen::CwiseUnaryOp<dummy_Op, Eigen::MatrixXd> view1(out);
// shorter:
auto view2 = out.unaryExpr(dummy_Op());
Eigen::MatrixXd result = view1 * view2;
// or directly write: out.unaryExpr(dummy_Op()) * out.unaryExpr(dummy_Op());
}
In my application, I want to determine at compile time whether an arbitrary functor type Func has a nullary call operator that can be invoked with a given explicit template argument T. Based on a previous SO answer that I found, I came up with the following:
#include <boost/hana.hpp>
#include <iostream>
#include <type_traits>
namespace hana = boost::hana;
namespace detail
{
template <typename T>
auto can_call = hana::is_valid([](auto &&f) ->
decltype(f.template operator()<T>()) { });
}
template <typename Func, typename T>
constexpr auto can_call() ->
decltype(detail::can_call<typename std::remove_reference<T>::type>(
std::declval<Func>())) { return {}; }
struct foo
{
template <typename T, typename =
std::enable_if_t<!std::is_same<T, char>::value>>
void operator()() const { }
};
int main()
{
std::cout << "char: " << can_call<foo, char>() << std::endl;
std::cout << "int: " << can_call<foo, int>() << std::endl;
}
I would expect this example to print out:
char: 0
int: 1
Since the char template argument type is explicitly enable_if-ed out in foo. I've tried the following compilers:
Apple clang v8.0.0: The example compiles and runs as expected.
mainline clang v3.9.1+ (via Wandbox): The example compiles and runs as expected.
mainline clang v3.6.0 - v3.8.1 (via Wandbox): The compiler dies with an internal error.
g++ 7.0 trunk, 20170410 (via Wandbox): The compilation fails with the following errors:
dd.cc: In instantiation of ‘auto detail::can_call<char>’:
dd.cc:15:14: required by substitution of ‘template<class Func, class T> constexpr decltype (can_call<typename std::remove_reference<_To>::type>(declval<Func>())) can_call() [with Func = foo; T = char]’
dd.cc:25:50: required from here
dd.cc:10:10: error: ‘auto detail::can_call<char>’ has incomplete type
auto can_call = hana::is_valid([](auto &&f) -> decltype(f.template operator()<T>()) { });
^~~~~~~~
dd.cc: In function ‘int main()’:
dd.cc:25:50: error: no matching function for call to ‘can_call<foo, char>()’
std::cout << "char: " << can_call<foo, char>() << std::endl;
^
dd.cc:14:16: note: candidate: template<class Func, class T> constexpr decltype (can_call<typename std::remove_reference<_To>::type>(declval<Func>())) can_call()
constexpr auto can_call() ->
^~~~~~~~
dd.cc:14:16: note: substitution of deduced template arguments resulted in errors seen above
dd.cc: In instantiation of ‘auto detail::can_call<int>’:
dd.cc:15:14: required by substitution of ‘template<class Func, class T> constexpr decltype (can_call<typename std::remove_reference<_To>::type>(declval<Func>())) can_call() [with Func = foo; T = int]’
dd.cc:26:48: required from here
dd.cc:10:10: error: ‘auto detail::can_call<int>’ has incomplete type
auto can_call = hana::is_valid([](auto &&f) -> decltype(f.template operator()<T>()) { });
^~~~~~~~
dd.cc:26:48: error: no matching function for call to ‘can_call<foo, int>()’
std::cout << "int: " << can_call<foo, int>() << std::endl;
^
dd.cc:14:16: note: candidate: template<class Func, class T> constexpr decltype (can_call<typename std::remove_reference<_To>::type>(declval<Func>())) can_call()
constexpr auto can_call() ->
^~~~~~~~
dd.cc:14:16: note: substitution of deduced template arguments resulted in errors seen above
It seems to not like my use of hana::is_valid() to determine whether the specified operator exists. However, I think the way I'm using it is consistent with its intended use.
Is this a bug in gcc, a more lenient implementation in contemporary clang versions, or did I implement this type of check incorrectly? It seems like this is definitely within Hana's wheelhouse; I'm just trying to wrap my head around its new model of constexpr metaprogramming.
Here is a workaround that uses a struct "functor" instead of a lambda and an extra layer of indirection for the type of the is_valid instance to appease gcc.
namespace detail
{
template <typename T>
struct check_can_call {
template <typename F>
constexpr auto operator()(F&& f) ->
decltype(f.template operator()<T>()) { }
};
template <typename T>
using is_call_valid = decltype(hana::is_valid(check_can_call<T>{}));
template <typename T>
constexpr is_call_valid<T> can_call{};
}
Given the following struct:
struct ABC
{
ABC(){cout << "ABC" << endl;}
~ABC() noexcept {cout << "~ABC" << endl;}
ABC(ABC const&) {cout << "copy" << endl;}
ABC(ABC&&) noexcept {cout << "move" << endl;}
ABC& operator=(ABC const&){cout << "copy=" << endl;}
ABC& operator=(ABC&&) noexcept {cout << "move=" << endl;}
};
The output of:
std::pair<std::string, ABC> myPair{{}, {}};
is:
ABC
copy
~ABC
~ABC
While the output of:
std::pair<std::string, ABC> myPair{{}, ABC{}};
is:
ABC
move
~ABC
~ABC
In attempting to understand the difference between the two I think I have identified that the first case is using copy-list-initialization, while the second one uses direct-list-initialization of an unnamed temporary (numbers 7 and 2, respectively, in here: http://en.cppreference.com/w/cpp/language/list_initialization).
Searching for similar questions I've found this: Why does the standard differentiate between direct-list-initialization and copy-list-initialization? and this: Does copy list initialization invoke copy ctor conceptually?.
The answers in those questions discuss the fact that for copy-list-initialization, the use of an explicit constructor would render the code ill-formed. In fact, if I make ABC's default constructor explicit, my first example won't compile but that is (perhaps) a different matter.
So, the question is: Why is the temporary copied in the first case but moved in the second? What prevents it from being moved in the case of copy-list-initialization?
As a note, the following code:
std::pair<std::string, ABC> myPair = std::make_pair<string, ABC>({}, {});
Also results in a call to ABC's move constructor (and no copy constructor call), but different mechanisms may be involved.
You can try the code out (using gcc-4.9.2 in C++14 mode) at: https://ideone.com/Kc8xIn
In general, braced-init-lists like {} are not expressions and do not have a type. If you have a function template
template<typename T> void f(T);
and call f( {} ), no type will be deduced for T, and type deduction will fail.
On the other hand, ABC{} is a prvalue expression of type ABC (an "explicit type conversion in functional notation"). For a call like f( ABC{} ), the function template can deduce the type ABC from this expression.
In C++14, as well as in C++11, std::pair has the following constructors [pairs.pair]; T1 and T2 are the names of the template parameter of the std::pair class template:
pair(const pair&) = default;
pair(pair&&) = default;
constexpr pair();
constexpr pair(const T1& x, const T2& y);
template<class U, class V> constexpr pair(U&& x, V&& y);
template<class U, class V> constexpr pair(const pair<U, V>& p);
template<class U, class V> constexpr pair(pair<U, V>&& p);
template <class... Args1, class... Args2>
pair(piecewise_construct_t, tuple<Args1...>, tuple<Args2...>);
Note that there is a constructor
constexpr pair(const T1& x, const T2& y); // (C)
But no
constexpr pair(T1&& x, T2&& y);
instead, there is a perfectly forwarding
template<class U, class V> constexpr pair(U&& x, V&& y); // (P)
If you try to initialize a std::pair with two initializers where at least one of them is a braced-init-list, the constructor (P) is not viable since it cannot deduce its template arguments.
(C) is not a constructor template. Its parameter types T1 const& and T2 const& are fixed by the class template parameters. A reference to a constant type can be initialized from an empty braced-init-list. This creates a temporary object that is bound to the reference. As the type referred to is const, the (C) constructor will copy its arguments into the class' data members.
When you initialize a pair via std::pair<T,U>{ T{}, U{} }, the T{} and U{} are prvalue-expressions. The constructor template (P) can deduce their types and is viable. The instantiation produced after type deduction is a better match than the (C) constructor, because (P) will produce rvalue-reference parameters and bind the prvalue arguments to them. (C) on the other hand binds the prvalue arguments to lvalue-references.
Why then does the live example move the second argument when called via std::pair<T,U>{ {}, U{} }?
libstdc++ defines additional constructors. Below is an extract of its std::pair implementation from 78536ab78e, omitting function definitions, some comments, and SFINAE. _T1 and _T2 are the names of the template parameters of the std::pair class template.
_GLIBCXX_CONSTEXPR pair();
_GLIBCXX_CONSTEXPR pair(const _T1& __a, const _T2& __b); // (C)
template<class _U1, class _U2>
constexpr pair(const pair<_U1, _U2>& __p);
constexpr pair(const pair&) = default;
constexpr pair(pair&&) = default;
// DR 811.
template<class _U1>
constexpr pair(_U1&& __x, const _T2& __y); // (X)
template<class _U2>
constexpr pair(const _T1& __x, _U2&& __y); // (E) <=====================
template<class _U1, class _U2>
constexpr pair(_U1&& __x, _U2&& __y); // (P)
template<class _U1, class _U2>
constexpr pair(pair<_U1, _U2>&& __p);
template<typename... _Args1, typename... _Args2>
pair(piecewise_construct_t, tuple<_Args1...>, tuple<_Args2...>);
Note the (E) constructor template: It will copy the first argument and perfectly forward the second. For an initialization like std::pair<T,U>{ {}, U{} }, it is viable because it only needs to deduce a type from the second argument. It is also a better match than (C) for the second argument, and hence a better match overall.
The "DR 811" comment is in the libstdc++ sources. It refers to LWG DR 811 which adds some SFINAE, but no new constructors.
The constructors (E) and (X) are a libstdc++ extension. I'm not sure if it's compliant, though.
libc++ on the other hand does not have this additional constructors. For the example std::pair<T,U>{ {}, U{} }, it will copy the second argument.
Live demo with both library implementations
I would like to achieve the following
#include <iostream>
unsigned foo(int i) {return i;};
unsigned bar(unsigned(*p)()) {/*Do important work*/return p();};
int main(void){
int integer = 42;
auto lambda = [integer] () -> unsigned {return foo(integer);};
unsigned number = bar(lambda);
std::cout << number << std::endl;
}
That is, bar is expecting a pointer to function with no arguments and returning unsigned. I can easily write a wrapper unsigned baz() {return foo(42);};and pass that one to bar(), but this has two drawbacks
it's a separate function, while I would prefer to construct the wrapper inline
I have to write a new wrapper for each expected value of `integer.
The idea is that bar() is doing some work, in the process invoking the function, that was passed to it. I have a suitable function, but it has an extra argument. That extra argument, however, is known at the point of passing the function to bar().
Is there a way to pull this off, or should I forget this approach and use templates? I have control over changing the interface (e.g. change the function pointer argument to std::function).`
The following code is a snippet of a tuple-like class where it is possible to get a reference to a given type in the tuple, or if that type is not found, the provided default value will be returned instead.
If the default value is a lvalue a reference must be returned, if the default value is a rvalue then a rvalue must be returned.
The following code illustrates the problem I'm having:
struct Foo {
Foo(int d) : data(d) {}
template <typename T, typename TT>
const TT get_or_default(TT&& t) const {
return data;
}
template <typename T, typename TT>
TT get_or_default(TT&& t) {
return data;
}
int data;
};
int main(int argc, char* argv[]) {
int i = 6;
const Foo foo1(5);
Foo foo2(5);
// compile error
foo1.get_or_default<int>(i);
// works
foo1.get_or_default<int>(5);
foo2.get_or_default<int>(i) = 4;
foo2.get_or_default<char>('a');
return 0;
}
When compiling this I get the following error:
cxx.cxx:6:20: error: binding of reference to type 'int' to a value of type 'const int' drops qualifiers
return data;
^~~~
cxx.cxx:23:14: note: in instantiation of function template specialization 'Foo::get_or_default<int, int &>' requested here
foo1.get_or_default<int>(i);
^
1 error generated.
There is a special rule for template argument deduction when the function parameter is of type T&& where T is a template parameter. That rule is:
If the function argument is an lvalue of type U, then U& is used in place of U for type deduction in this case.
It's used to allow perfect forwarding. Basically, it means that T&& for a template parameter T is a "universal reference."
In your case, since i is indeed an lvalue, TT is deduced to int&. Applying a const to that is ignored (it would apply to the reference itself, not to the type referred to), so the fucntion instantiated from the template looks something like this:
int& get_or_default(int& t) const {
return data;
}
And since the function is const, data is considered const as well and so it cannot bind to a non-const reference.