Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

std::bind result member

46 views
Skip to first unread message

Helmut Zeisel

unread,
Nov 10, 2014, 4:00:03 AM11/10/14
to
In

http://en.cppreference.com/w/cpp/utility/functional/bind

heißt es:

"The return type of std::bind holds a member object of type std::decay<F>::type constructed from std::forward<F>(f)"

Ich würde gerne auf dieses member object zugreifen. Wie geht das?

Helmut

Daniel Krügler

unread,
Nov 10, 2014, 1:30:03 PM11/10/14
to
Kannst du kurz erklären, was dein eigentliches Ziel ist? Sobald du std::bind aufgerufen hast, hast du Zugriff auf ein ziemlich opakes Ergebnis. Der Ergebnistyp garantiert, dass er sich wie ein sog. Funktions-Objekt verhält, d.h. du kannst es ähnlich zu einer Funktion unter Angabe von Funktionsargumenten aufrufen. Unter bestimmten Umständen muss der Ergebnistyp ausserdem ein typedef result_type definieren, welches den Typ des Ergebnisses des Funktionsaufruf-Operators zurückgibt.

Besten Gruß aus Bremen,

Daniel Krügler

Helmut Zeisel

unread,
Nov 11, 2014, 3:30:04 AM11/11/14
to
Am Montag, 10. November 2014 19:30:03 UTC+1 schrieb Daniel Krügler:

> Kannst du kurz erklären, was dein eigentliches Ziel ist?

Kurz geht's leider nicht, der entsprechende etwas längere Code ist unten.
Die Frage ist, ob ich die zweite Version von make_array_view (die mit 3 Argumenten) wirklich brauche, obwohl ja die mit std::bind erzeugte Index-Funktion eigentlich die Information des dritten Element bereits enthält.

Helmut

================================ Code ===========================
#include <iostream>
#include <memory>
#include <utility>
#include <array>
#include <vector>
#include <iterator>
#include <functional>
#include <cassert>

template <typename Container_ptr, typename Index>
struct array_view
{
typedef typename std::pointer_traits<Container_ptr>::element_type container_type;
typedef typename container_type::reference reference;
typedef typename container_type::const_reference const_reference;
array_view(Container_ptr container_ptr, Index index):
container_ptr_(container_ptr), index_(index) {}

template <typename ...Args> reference operator()(Args&& ... args)
{
return (*container_ptr_)[index_(std::forward<Args>(args)...)];
}
template <typename ...Args> const_reference operator()(Args&& ... args) const
{
return (*container_ptr_)[index_(std::forward<Args>(args)...)];
}

private:
Container_ptr container_ptr_;
Index index_;
};

template <typename Container_ptr, typename Index>
array_view<Container_ptr, Index> make_array_view(Container_ptr container_ptr, Index index)
{
assert(container_ptr->size() >= index.size());
return array_view<Container_ptr, Index>(container_ptr, index);
}

// Do I really need this?
template <typename Container_ptr, typename Index>
array_view<Container_ptr, Index> make_array_view(Container_ptr container_ptr, Index index, std::size_t min_size)
{
assert(container_ptr->size() >= min_size);
return array_view<Container_ptr, Index>(container_ptr, index);
}

struct col_major_index
{
col_major_index(std::size_t m, std::size_t n): dim_{m,n} {}
std::size_t dim(std::size_t i) const
{
return dim_[i];
}
std::size_t size() const
{
return dim_[0]*dim_[1];
}
std::size_t operator()(std::size_t i, std::size_t j) const
{
return i + j*dim_[0];
}
private:
std::array<std::size_t, 2> dim_;
};


int main()
{
std::size_t m= 6;
std::size_t n= 7;
col_major_index idx(m,n);
std::vector<double> v(idx.size());
auto a=make_array_view(&v,idx);

for(std::size_t j=0; j!=n; ++j)
{
for(std::size_t i= 0; i!=m; ++i)
{
a(i,j) = 10*i + j;
}
}

std::ostream_iterator<double> out_it (std::cout,", ");
std::copy ( v.begin(), v.end(), out_it );
std::cout << std::endl;

// Is it really necessary to add the argument idx.size()?
auto row2 = make_array_view(&v, std::bind(idx,2,std::placeholders::_1),idx.size());
for(std::size_t j=0; j!=n; ++j)
{
std::cout << row2(j) << ",";
}
std::cout << std::endl;

return 0.;
}
=========================== Ende ==================================

Daniel Krügler

unread,
Nov 11, 2014, 8:50:02 AM11/11/14
to
Am Dienstag, 11. November 2014 09:30:04 UTC+1 schrieb Helmut Zeisel:
> Am Montag, 10. November 2014 19:30:03 UTC+1 schrieb Daniel Krügler:
>
> > Kannst du kurz erklären, was dein eigentliches Ziel ist?
>
> Kurz geht's leider nicht, der entsprechende etwas längere Code ist unten.
> Die Frage ist, ob ich die zweite Version von make_array_view (die mit 3 Argumenten) wirklich brauche, obwohl ja die mit std::bind erzeugte Index-Funktion eigentlich die Information des dritten Element bereits enthält.

Nein, die brauchst du nicht.
Damit obiges Template mit einem bind-Ergebnis funktioniert, musst du die Zeile

"assert(container_ptr->size() >= index.size());"

entfernen. Das Ergebnis von Bind ist ein Funktionsobjekt (Genauer: Call-Wrapper) und dieser Typ hat keine Member-Funktion size().

> // Do I really need this?
> template <typename Container_ptr, typename Index>
> array_view<Container_ptr, Index> make_array_view(Container_ptr container_ptr, Index index, std::size_t min_size)
> {
> assert(container_ptr->size() >= min_size);
> return array_view<Container_ptr, Index>(container_ptr, index);
> }

Unnötig.

> struct col_major_index
> {
> col_major_index(std::size_t m, std::size_t n): dim_{m,n} {}
> std::size_t dim(std::size_t i) const
> {
> return dim_[i];
> }
> std::size_t size() const
> {
> return dim_[0]*dim_[1];
> }
> std::size_t operator()(std::size_t i, std::size_t j) const
> {
> return i + j*dim_[0];
> }
> private:
> std::array<std::size_t, 2> dim_;
> };
>
>
> int main()
> {
> std::size_t m= 6;
> std::size_t n= 7;
> col_major_index idx(m,n);
> std::vector<double> v(idx.size());
> auto a=make_array_view(&v,idx);
>
> for(std::size_t j=0; j!=n; ++j)
> {
> for(std::size_t i= 0; i!=m; ++i)
> {
> a(i,j) = 10*i + j;
> }
> }
>
> std::ostream_iterator<double> out_it (std::cout,", ");
> std::copy ( v.begin(), v.end(), out_it );
> std::cout << std::endl;
>
> // Is it really necessary to add the argument idx.size()?
> auto row2 = make_array_view(&v, std::bind(idx,2,std::placeholders::_1),idx.size());

Nein. Wenn du den zweiten Overload entfernt hast und deine verbleibende make_array_view-Überladung gefixt hast, sollte es gehen.

Besten Gruß aus Bremen,

- Daniel Krügler

Helmut Zeisel

unread,
Nov 11, 2014, 9:10:03 AM11/11/14
to
Am Dienstag, 11. November 2014 14:50:02 UTC+1 schrieb Daniel Krügler:

> Damit obiges Template mit einem bind-Ergebnis funktioniert, musst du die Zeile
>
> "assert(container_ptr->size() >= index.size());"
>
> entfernen.

Will ich aber nicht. Ich möchte zumindest in der Debug-Version überprüfen, ob der Container auch wirklich groß genug ist.

> Das Ergebnis von Bind ist ein Funktionsobjekt (Genauer: Call-Wrapper) und
> dieser Typ hat keine Member-Funktion size().

Genau das ist das Problem. Intern hat das Funktionsobjekt zwar einen Zugriff auf size(), der wird aber nicht nach außen weitergereicht. Übrigens betrifft das nicht nur size(), sondern auch dim(). Auzf dim() hätte ich ebenfalls gerne Zugriff.

Helmut

Daniel Krügler

unread,
Nov 11, 2014, 9:30:04 AM11/11/14
to
Am Dienstag, 11. November 2014 15:10:03 UTC+1 schrieb Helmut Zeisel:
> Am Dienstag, 11. November 2014 14:50:02 UTC+1 schrieb Daniel Krügler:
>
> > Damit obiges Template mit einem bind-Ergebnis funktioniert, musst du die Zeile
> >
> > "assert(container_ptr->size() >= index.size());"
> >
> > entfernen.
>
> Will ich aber nicht. Ich möchte zumindest in der Debug-Version überprüfen, ob der Container auch wirklich groß genug ist.

Dann du den Sinn von bind nicht verstanden bzw. bind ist nicht das richtige Tool für dich: Bind liefert einen Callwrapper und als solcher bietet er dir nur den Funktionsaufrufoperator an.

Helmut Zeisel

unread,
Nov 12, 2014, 2:50:03 AM11/12/14
to
Am Dienstag, 11. November 2014 15:30:04 UTC+1 schrieb Daniel Krügler:

> Dann du den Sinn von bind nicht verstanden bzw. bind ist nicht das richtige Tool für dich: Bind liefert einen Callwrapper und als solcher bietet er dir nur den Funktionsaufrufoperator an.

Bind passt schon. Ich muss nur den von Bind gelieferten Callwrapper gemeinsam mit der von mir benötigten Information in meinen eigenen Wrapper einpacken. Das ist zwar weniger effizient und weniger elegant, funktioniert aber.

Helmut

Christian Steins

unread,
Dec 7, 2016, 7:50:05 AM12/7/16
to
Hi,
falls möglich sollte auf std:bind verzichtet werden. Bessere Alternative
sind Lambdas.


Christian

Helmut Zeisel

unread,
Jan 7, 2017, 5:50:03 AM1/7/17
to
Würde mir das im konkreten Fall helfen (kann ich also von außen auf die "captured" (wie heißt das auf deutsch? "gefangenen") Variablen zugreifen?

Helmut

Stefan Ram

unread,
Jan 7, 2017, 10:50:03 AM1/7/17
to
Helmut Zeisel <zei...@liwest.at> writes:
>Würde mir das im konkreten Fall helfen (kann ich also von
>außen auf die "captured" (wie heißt das auf deutsch?
>"gefangenen") Variablen zugreifen?

Man könnte natürlich eine Funktion schreiben, die bei
bestimmten Argumentwerten Referenzen auf jene Objekte
liefert, aber es könnten besser sein, hierfür eine
Funktor-Klasse zu schreiben.
0 new messages