1

Why std::cout does not compile in this code snippet,

#include<future>
#include<iostream>
#include<array>
#include<algorithm>

std::array<int, 100> arr;
int sum=0;

struct Wrapper
{   
    void consume()
    {
        std::cout << std::this_thread::get_id() << std::endl;
        std::for_each(arr.begin(), arr.end(), [&sum](int val) {sum+=val; });
        std::cout << sum << std::endl;
    }

    bool produce()
    {
        std::cout << std::this_thread::get_id() << std::endl;

        auto temp = { 1,0,3 };
        return true;
    }
};


int main()
{
    std::fill(arr.begin(), arr.end(), 1);

    std::cout << std::this_thread::get_id() << std::endl;

    Wrapper wrap;
    std::future<bool> fut = std::async(std::launch::async, &Wrapper::produce, &wrap);

    if (fut.get())
        std::async(std::launch::async, &Wrapper::consume, &wrap).get();

}

whereas it compiles in another similar code snippet:


#include <iostream>
#include <thread>

void dosomework()
{
    std::cout << std::this_thread::get_id() << std::endl;
}

int main()
{
    for (int i = 0; i < 10; ++i){
        std::thread connectthread([](){
            dosomework();
        });
        std::cout << "connectthread:" << connectthread.get_id() << std::endl;
        connectthread.join(); 
    }
    return 0;
}

Here is what the compiler comlains for the former code snippet:

<source>: In member function 'void Wrapper::consume()':
<source>:14:53: warning: capture of variable 'sum' with non-automatic storage duration
   14 |             std::for_each(arr.begin(), arr.end(), [&sum](int val) {sum+=val; });
      |                                                     ^~~
<source>:7:9: note: 'int sum' declared here
    7 |     int sum=0;
      |         ^~~
/opt/compiler-explorer/gcc-12.1.0/bin/../lib/gcc/x86_64-linux-gnu/12.1.0/../../../../x86_64-linux-gnu/bin/ld: /tmp/cck5848f.o: in function `main':
<source>:32: undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::thread::id)'
/opt/compiler-explorer/gcc-12.1.0/bin/../lib/gcc/x86_64-linux-gnu/12.1.0/../../../../x86_64-linux-gnu/bin/ld: /tmp/cck5848f.o: in function `Wrapper::consume()':
<source>:13: undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::thread::id)'
/opt/compiler-explorer/gcc-12.1.0/bin/../lib/gcc/x86_64-linux-gnu/12.1.0/../../../../x86_64-linux-gnu/bin/ld: /tmp/cck5848f.o: in function `Wrapper::produce()':
<source>:20: undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::thread::id)'
collect2: error: ld returned 1 exit status

Updated: What a surprise, it compiles on this online compiler.

John
  • 2,963
  • 11
  • 33
  • Why are you capturing a global variable? Just don't capture `&sum` and it works fine. [Demo](https://onlinegdb.com/slDSxvkqv8) – Jason Jun 07 '22 at 11:44
  • Er, what a surprise, this post has been closed. The main question is about `std::cout << std::this_thread::get_id()` . – John Jun 07 '22 at 11:48
  • `std::cout << std::this_thread::get_id()` compiles fine. [Demo](https://www.onlinegdb.com/slDSxvkqv8) – Jason Jun 07 '22 at 11:50
  • Again it compiles fine on godbolt. See [demo](https://godbolt.org/z/T5dKjbsW7). – Jason Jun 07 '22 at 11:56
  • @AnoopRana Er, I am totally confused now. Then what's wrong with [this code snippet](https://godbolt.org/z/f1c3q5357)? I really can't any major difference between your code snippet and mine. – John Jun 07 '22 at 12:01
  • 1
    You're getting a linker error and not a compiler error. Don't worry about the linker error. Just use the demo link i gave. – Jason Jun 07 '22 at 12:03
  • 1
    Is it the _warning_ or the linker error you are asking about? To resolve the linker error we'd need to see the build command line. Are you perhaps building with the gcc driver rather than g++? The former does not implicitly link libstdc++. – Clifford Jun 07 '22 at 12:18

1 Answers1

1

It needs #include <thread> and it compiles.

John
  • 2,963
  • 11
  • 33
  • Just a simple oversight. Basically a typo. – Eljay Jun 07 '22 at 11:55
  • @Eljay Sorry for my poor English, could you please repeat it again in simple words? – John Jun 07 '22 at 11:57
  • The original code was missing `#include `. That's basically a typo, and there's no question here. – Eljay Jun 07 '22 at 11:59
  • @Eljay There is no such header for [this code snippet](https://godbolt.org/z/4oqhfn9hM), but it compiles indeed. What a surprise! – John Jun 07 '22 at 12:03
  • That does not explain the linker errors. You seem to be permanently astonished! It is not that surprising `` is most likely indirectly included via `` through nesting of includes. – Clifford Jun 07 '22 at 12:19
  • 2
    Some standard headers are *required* to include other specific standard headers. Otherwise, standard headers *may* include other standard headers as the compiler vendor deigns. Code relying on that indirect dependency can run afoul of missing headers. The general guidance for all source files (h and cpp) is **include what you use**. – Eljay Jun 07 '22 at 12:20
  • 1
    https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-api-4.5/a00879_source.html includes `thread` as I suggested. But what @Eljay said - you should not assume that. – Clifford Jun 07 '22 at 12:26