"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:
Post a Comment