Sunday, August 9, 2015

Digest for comp.lang.c++@googlegroups.com - 16 updates in 4 topics

"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Aug 09 08:55AM +0200

On 08-Aug-15 11:37 PM, Doug Mika wrote:
> Could anyone tell me why the following won't compile? To be honest, I don't know
> where to begin with the compiler error messages, even the first one.
 
So why do you omit the error messages, the compiler information, etc.?
 
Here's a FAQ item that guides about posting about this kind of issue:
 
"How do I post a question about code that doesn't work correctly?"
http://www.cs.rit.edu/~mjh/docs/c++-faq/how-to-post.html#faq-5.8
 
The link is to mirror site, that will probably soon disappear due to the
FAQ's migration to isocpp.org.
 
Unfortunately the C++ FAQ has only been partially migrated to
https://isocpp.org/faq, and the above item is one that as yet has no
text there, but still has the text removed over at parashift (original
FAQ residence). And as another example that the FAQ is not currently
complete, the original FAQ's item about newbie guides still directs the
reader to my old tutorial, which has been offline for umpteen years! But
in spite of such problems I do recommend checking out the FAQ, before
posting a question -- chances are it's already been answered, or that
the FAQ has some good advice about it or about posting... ;-)
 
 
> std::future<int> result = spawn_task(cube, myInt);
> cout<<"The result is: "<<result.get()<<endl;
> }
 
General advice: start with something simpler.
 
Cheers & hth.,
 
- Alf
 
--
Using Thunderbird as Usenet client, Eternal September as NNTP server.
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Aug 09 10:56AM +0100

On Sat, 8 Aug 2015 14:37:59 -0700 (PDT)
> Could anyone tell me why the following won't compile? To be honest,
> I don't know where to begin with the compiler error messages, even
> the first one.
[snip]
 
First, you need to learn how to construct a std::packaged_task object
of type std::packaged_task<int()> from your cube() function and its
int argument. Writing other superfluous code (which contains different
errors) before you have done that is unhelpful.
 
Furthermore, you have already been told how to construct such a
std::packaged_task object in a previous posting of yours - use a lambda
expression or std::bind. If you didn't understand the responses you
received, try reading them again and online reference material for
those.
 
Once you have done that try constructing a thread object from the
packaged_task object. Once you have done that, do more research on how
std::move and std::forward work.
 
Chris
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Aug 09 11:10AM +0100

On Sun, 9 Aug 2015 10:56:54 +0100
 
> Once you have done that try constructing a thread object from the
> packaged_task object. Once you have done that, do more research on how
> std::move and std::forward work.
 
I should add for completeness (and for your self-learning purposes) that
alternatively you can construct a std::packaged_task<int(int)> object
from your cube function in the way you proposed and then bind the
argument when constructing the thread object, but that will not be the
approach to adopt when writing your generic task queue: as you
recognised in your post under the heading "packaged_task", that
requires a std::packaged_task<T()> object.
 
Play around with it and you should get the hang of it.
 
Chris
Doug Mika <dougmmika@gmail.com>: Aug 09 11:34AM -0700

On Sunday, August 9, 2015 at 5:15:28 AM UTC-5, Chris Vine wrote:
> requires a std::packaged_task<T()> object.
 
> Play around with it and you should get the hang of it.
 
> Chris
 
I got this code from a book on threading in c++, and I found the code useful, but it doesn't compile on cpp.sh. Unfortunately I have not yet managed to read a book on templates, but I hope to get around to it soon enough. I was going to ask a follow up question: how I could change the code above to allow for functions which take more than one parameter. I guess the answer would help me decipher the workings of templates before I get to read a book on it.
Doug Mika <dougmmika@gmail.com>: Aug 09 12:20PM -0700

I actually found some modified version of the function, and here it is:
// Example program
#include <iostream>
#include <string>
#include <future>
#include <type_traits>
#include <string>
 
template<typename F, typename A>
std::future<typename std::result_of<F(A)>::type> spawn_task(F&& f, A&& a){
typedef typename std::result_of<F(A)>::type result_type;
std::packaged_task<result_type(A)> task(std::move(f));
std::future<result_type> res(task.get_future());
std::thread t(std::move(task),std::move(a));
t.detach();
return res;
}
 
int cube(int x){
return x*x*x;
}
 
int main(){
int myInt=3;
auto result = spawn_task(cube, myInt);
std::cout<<"The result is: "<<result.get()<<std::endl;
}
 
The only problem now is with the creation of the thread t:
std::thread t(std::move(task),std::move(a));
 
Why does the compiler say the following: (and what does that exactly mean?)
 
required from 'std::future<typename std::result_of<F(A)>::type> spawn_task(F&&, A&&) [with F = int (&)(int); A = int&; typename std::result_of<F(A)>::type = int]'
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Aug 09 09:05PM +0100

On Sun, 9 Aug 2015 12:20:45 -0700 (PDT)
 
> required from 'std::future<typename std::result_of<F(A)>::type>
> spawn_task(F&&, A&&) [with F = int (&)(int); A = int&; typename
> std::result_of<F(A)>::type = int]'
 
The problem is that if the integer passed to spawn_task() is a lvalue,
as it is here, then A&& collapses to int& which causes instantiation
failure of the thread object when passed a std::packaged_task<int(int&)>
object. The other problem is that you are not using std::move correctly.
Here is a corrected version which deals with the issues with your code,
and makes some other clean-ups (you can use decltype here rather than
having to use std::result_of), in C++11 compatible form: some shortening
is possible with C++14. On std::move/std::forward, I suggest you read
up on what are sometimes called "universal" references, "collapsible"
references or "forwarding" references. The code below is tested with
gcc-5.1 and clang-3.6.0.
 
As I have mentioned elsewhere, I would not do it this way. I would use
std::bind to construct a std::packaged_task<T()> object, which saves
having to futz around with std::remove_reference.
 
Note also that if you were to use std::result_of, you need to apply
'typename' to the std::result_of<...>::type expression because it is
a dependent type (see also the use of 'typename' with
std::remove_reference below).
 
 
#include <iostream>
#include <string>
#include <future>
#include <type_traits>
 
 
template<typename F, typename A>
auto spawn_task(F&& f, A&& a) -> std::future<decltype(f(a))> {
typedef decltype(f(a)) result_type;
std::packaged_task<result_type(typename std::remove_reference<A>::type)> task{std::forward<F>(f)};
std::future<result_type> res{task.get_future()};
std::thread t{std::move(task), std::forward<A>(a)};
t.detach();
return res;
}
 
int cube(int x){
return x*x*x;
}
 
int main()
{
int myInt=3;
std::future<int> result = spawn_task(cube, myInt);
std::cout << "The result is: " << result.get() << std::endl;
}
Doug Mika <dougmmika@gmail.com>: Aug 09 02:55PM -0700

On Sunday, August 9, 2015 at 3:10:47 PM UTC-5, Chris Vine wrote:
> std::future<int> result = spawn_task(cube, myInt);
> std::cout << "The result is: " << result.get() << std::endl;
> }
 
Much thanks for the corrected version, appreciated. I did manage to get mine to work, all that was needed was a std::move in the call to spawn thread. Reason probably as you explained. And I guess the instantiation failure is because passing reference parameters in function run in threads requires std::ref?
 
I was wondering where you could learn these things. I got this example from a book, but it certainly did not explain, line by line, what each line did. And it was buggy on top of that. I mean, the error message the compiler threw at me, well, I didn't know what the problem was in the least.
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Aug 10 12:14AM +0100

On Sun, 9 Aug 2015 14:55:32 -0700 (PDT)
Doug Mika <dougmmika@gmail.com> wrote:
[snip]
> what each line did. And it was buggy on top of that. I mean, the
> error message the compiler threw at me, well, I didn't know what the
> problem was in the least.
 
It works if you pass std::move(myInt) to spawn_task() because that
converts the lvalue to a rvalue and this causes A in spawn_task() to
be deduced as int, which works. Obviously however, requiring the
argument to be passed only as an rvalue is completely wrong: it "works"
for that particular case only as a side effect of a defective design.
As you suggest, it would also compile for lvalues if you passed the
argument to std::thread's constructor via std::ref. However that would
also be completely wrong for this usage - first, it would no longer work
for rvalue arguments, and secondly you should almost never pass an
argument to std::thread by reference rather than by value because the
variable passed may be out of scope by the time it is accessed by the
thread concerned. (The last point would not be true here though because
your code blocks on std::future::get() within the scope of the int
argument, but that is just an artifact of your simplistic example.)
 
It is difficult to believe that the code you have posted is actually in
a published book. Perhaps you are "converting" C++98 code using boost
into C++11 code using the standard library, but not doing so
correctly - C++98 does not have rvalue references, which means that it
does not have std::move, std::forward or collapsible references. If the
code really was in a book in the form in which you have presented it,
throw it in the bin.
 
This is basic stuff about lvalue and rvalue types, perfect forwarding
and reference collapsing, and is not specific to threads. Any decent
book which purports to cover C++11 should deal with it. The other
point to make is that this is normally only an issue for library
writers. Your code is redundant by virtue of std::async.
 
Chris
Victor Bazarov <v.bazarov@comcast.invalid>: Aug 08 08:22PM -0400

On 8/8/2015 7:27 PM, K. Frank wrote:
 
> But by the time you do that, you might as well just
> revert to the old-school "for (unsigned i = 0, ...)"
> loop.
 
Not sure how to do the last thing, but the first is easy if you keep a
flag and set it as soon as the operation is done:
 
bool done1st = false;
for (auto x : v)
{
if (!done1st)
{
// do 1st thing with x
done1st = true;
}
... // do stuff with x
}
 
Of course, it could be used to not do the first thing as well. For
instance you can put the comma in front of only the second and later
elements:
 
bool first = true;
for (auto x : v)
{
if (!first)
mystream << ", ";
mystream << x;
first = false;
}
 
V
--
I do not respond to top-posted replies, please don't ask
Marcel Mueller <news.5.maazl@spamgourmet.org>: Aug 09 02:33AM +0200

On 09.08.15 01.27, K. Frank wrote:
> to print out a vector in parenthesized, comma-separated
> notation:
 
> (1, 2, 3, 4, 5)
 
string ret = "(";
for (...)
{ if (ret.size() != 1)
ret = ret.append(",");
ret = ret.append(...); // content
}
ret = ret.append(")");
 
Of course, this works only when the content cannot be empty. Otherwise
you need a bool first = true;
 
> Is there a nice idiom for this using "for (auto x : y)"?
 
I have seen different variants, all of them not that pretty.
(Btw. the ABAP language has a keyword for this common purpose.)
 
> if (++i == collection.size()) break;
> // print ", "
> }
 
The invocation of size() could be slow on some container types. Although
this is uncommon. But size() might not even exist in case of forward
only iterations.
 
> But by the time you do that, you might as well just
> revert to the old-school "for (unsigned i = 0, ...)"
> loop.
 
This makes no significant difference.
 
 
Marcel
Louis Krupp <lkrupp@nospam.pssw.com.invalid>: Aug 08 11:38PM -0600

On Sat, 8 Aug 2015 16:27:35 -0700 (PDT), "K. Frank"
 
> for (auto x : collection) // do stuff with x;
 
>But lots of times you want to give slightly special
>treatment to the first or last element:
<snip>
 
>But by the time you do that, you might as well just
>revert to the old-school "for (unsigned i = 0, ...)"
>loop.
 
An easy way to do the commas would be something like this:
 
const char* delim = "";
for (auto x : collection) {
print delim;
print x;
delim = ", ";
}
 
If you want to do something special for the last element in the
collection, and you don't want to compare an index to the collection
size, consider appending a sentinel element to the collection. When
you see it, you know you've hit the end of the stuff you were really
interested in.
 
Louis
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Aug 09 08:40AM +0200

On 09-Aug-15 1:27 AM, K. Frank wrote:
> // do stuff with collection[i];
> if (i == collection.size() - 1) // do something special;
> }
 
The Python language has a nice idiom for this, namely passing the range
you want to an `enumerate` function that produces an (index, value) pair
for each value from that range. Defined as a continuation it's pretty
simple,
 
def enumerate(sequence, start=0):
n = start
for elem in sequence:
yield n, elem
n += 1
 
The Boost library provides similar functionality for C++, although with
a silly pipe-syntax (it's a bit over-engineered), and hidden so well
that I couldn't find it now by simple googling. It's probably in the
vicinity of Boost ranges. But exactly where, that's the question.
 
However, I was able to find a similar utility that I just wrote up for
an answer to some forum question, apparently in comp.lang.c++ (this
group) and evidently this year:
 
<code file="Indexer.hpp">
#pragma once
// Copyright (c) 2015 Alf P. Steinbach
 
#include <iterator> // std::iterator_traits
#include <stddef.h> // ptrdiff_t
#include <type_traits> // std::remove_reference
#include <utility> // std::pair, std::declval, std::begin,
std::end, std::move
 
namespace progrock{ namespace cppx{
using std::begin;
using std::declval;
using std::end;
using std::iterator;
using std::iterator_traits;
using std::move;
using std::pair;
using std::random_access_iterator_tag;
using std::remove_reference;
 
using Index = ptrdiff_t;
 
template< class Underlying_iter_tp, class Index_tp = Index >
class Indexer
{
public:
using Underlying_iter = Underlying_iter_tp;
using Index = Index_tp;
 
using Item = typename remove_reference<decltype((
*declval<Underlying_iter>() ))>::type;
 
struct Numbered_item
: pair<Index, Item*>
{
using Pair = pair<Index, Item*>;
using Pair::pair; // Constructors.
using Pair::first;
using Pair::second;
 
auto index() const -> Index { return first; }
auto value() -> Item& { return *second; }
auto value() const -> Item const& { return *second; }
};
 
private:
Underlying_iter under_begin_;
Underlying_iter under_end_;
 
class Iter
: public iterator<
typename
iterator_traits<Underlying_iter>::iterator_category,
Numbered_item,
typename iterator_traits<Underlying_iter>::difference_type,
typename iterator_traits<Underlying_iter>::pointer,
typename iterator_traits<Underlying_iter>::reference
 
{
friend class Indexer;
private:
Underlying_iter it_;
Numbered_item item_;
 
Iter( Underlying_iter it )
: it_( move( it ) )
, item_( 0, &*it ) // TODO: Check validity
{}
 
public:
friend
auto operator<( Iter const& a, Iter const& b )
-> bool
{ return (a.it_ < b.it_); }
 
friend
auto operator<=( Iter const& a, Iter const& b )
-> bool
{ return (a.it_ <= b.it_); }
 
friend
auto operator==( Iter const& a, Iter const& b )
-> bool
{ return (a.it_ == b.it_); }
 
friend
auto operator>=( Iter const& a, Iter const& b )
-> bool
{ return (a.it_ >= b.it_); }
 
friend
auto operator>( Iter const& a, Iter const& b )
-> bool
{ return (a.it_ > b.it_); }
 
friend
auto operator!=( Iter const& a, Iter const& b )
-> bool
{ return (a.it_ != b.it_); }
 
auto operator++()
-> Iter&
{
++it_;
++item_.first; item_.second = &*it_;
return *this;
}
 
auto operator++( int )
-> Iter
{
Iter original = *this;
++*this;
return original;
}
 
auto operator*()
-> Numbered_item const&
{ return item_; }
};
 
public:
auto begin() -> Iter { return Iter( under_begin_ ); }
auto end() -> Iter { return Iter( under_end_ ); }
 
Indexer( Underlying_iter const begin_iter, Underlying_iter
const end_iter )
: under_begin_( begin_iter )
, under_end_( end_iter )
{}
};
 
template< class Collection_tp >
auto indexed( Collection_tp& c )
-> Indexer<decltype( begin( c ) )>
{ return Indexer<decltype( begin( c ) )>( begin( c ), end( c ) ); }
}} // namespace progrock::cppx
</code>
 
I'm pretty sure that this has not been tested for anything but the
simplest possible example, in the original question, whatever it was.
 
And I would usully not define explicitly all those comparison operators,
but instead inherit a template that generates them.
 
So, it's more like example proof-of-concept code than something to use
directly as-is, but I think you may be able to at least at first just
use it directly.
 
 
> notation:
 
> (1, 2, 3, 4, 5)
 
> Is there a nice idiom for this using "for (auto x : y)"?
 
<code>
#include <p/cppx/collections/Indexer.hpp>
using namespace progrock;
 
#include <iostream>
#include <vector>
using namespace std;
 
auto main() -> int
{
using cppx::indexed;
 
vector<int> const v = {1, 2, 3, 4, 5};
wcout << "(";
for( auto item : indexed( v ) )
{
wcout << (item.index() > 0? ", " : "") << item.value();
}
wcout << ")" << endl;
}
</code>
 
<snip>
 
Cheers & hth.,
 
- Alf
 
--
Using Thunderbird as Usenet client, Eternal September as NNTP server.
Jorgen Grahn <grahn+nntp@snipabacken.se>: Aug 09 10:38PM

On Sat, 2015-08-08, K. Frank wrote:
 
> for (auto x : collection) // do stuff with x;
 
> But lots of times you want to give slightly special
> treatment to the first or last element:
...
 
I noted this just like you did, but eventually concluded that "ok, so
I can't use the new syntax in that special case. The simplification
comes at a price."
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
szyk100@o2.pl: Aug 09 10:11AM -0700

Hi
 
I am trying to compile omniORB-4.2.0 with VC++14 under Windows 7 64bit. But I have encountered some problems. Some of them I solve but one remain. Now I get compiler error:
error C1083: Cannot open include file: 'io.h': No such file or directory
In true this file does not exists in: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include
But I found it in two werid directories:
C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt
C:\Program Files (x86)\Windows Kits\10\Include\10.0.10150.0\ucrt
 
Omniorb uses gnu make scripts to build (with Cygwin), but I have not idea: How to force VC++ to include one of those directories?
 
please help me, regards
Szyk Cech
Paavo Helde <myfirstname@osa.pri.ee>: Aug 09 01:24PM -0500

szyk100@o2.pl wrote in
> file: 'io.h': No such file or directory In true this file does not
> exists in: C:\Program Files (x86)\Microsoft Visual Studio
> 14.0\VC\include
 
io.h is not a standard C++ header so in principle VC++14 has no
obligation to provide one. But I guess normally they do and this means
you just have a broken installation.
 
> But I found it in two werid directories:
> C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt
> C:\Program Files (x86)\Windows Kits\10\Include\10.0.10150.0\ucrt
 
That the name of the file is the same does not guarantee that the content
is the same one as needed.
 
 
> Omniorb uses gnu make scripts to build (with Cygwin), but I have not
> idea: How to force VC++ to include one of those directories?
 
By adding it to the include search paths? But this may not solve your
problems, if your installation of VS2014 is broken, you will likely have
much more problems than that. You might get better response from a MS-
specific forum, this group is mostly concerned with pure C++ issues.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Aug 09 08:57AM +0200

On 08-Aug-15 9:19 PM, Diego Martins wrote:
 
> Template metaprogramming is for those who enjoy using a pure, non-strict, functional programming language, with pattern matching within C++. If there is anything truly worth in the language that's the completely serendipitous emergence of this important idiom to the point of it being a core practice for lots of really useful and advanced code. One thing that is currently missing is having the opportunity to seamlessly define strings as types in situ within a template parameter list as a language feature.
 
> I have been using various personal implementations in my own code for this, though I think that it is such a fundamental construct it should also exist in stand-alone mode. This is a fast compile-time wise, single-header, no-dependencies, standard-compliant C++ library offering a seamless way to enjoy compile time strings as individual, distinct types.
 
> typedef typestring_is("Hello!") test; /* irqus::typestring<'H','e','l','l','o','!'> */
 
Lazy me I'm just asking, how on Earth does that macro split the string
into its individual characters?
 
Cheers,
 
- Alf
 
--
Using Thunderbird as Usenet client, Eternal September as NNTP server.
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: