I was following a talk on YouTube by Kelvin Henney based on the idiom of Functional C++... About 50 minutes into the video he starts showing an example class structure that he named channel
. Then he writes the simple fizzbuzz
function and is going to pass that into a server like piece of code using threads. I'm using the code from his video which can be found here: Kevlin Henney - Functional C++
However, when I try to compile the program, Visual Studio is generating the C2661
compiler error pointing to std::tuple
... which is coming from the std::tread
's constructor within my code.
main.cpp
#include <iostream>
#include <exception>
#include <string>
#include <thread>
#include "server.h"
std::string fizzbuzz(int n) {
return
n % 15 == 0 ? "FizzBuzz" :
n % 3 == 0 ? "Fizz" :
n % 5 == 0 ? "Buzz" :
std::to_string(n);
}
void fizzbuzzer(channel<int> & in, channel<std::string> & out) {
for (;;)
{
int n;
in.receive(n);
out.send(fizzbuzz(n));
}
}
int main() {
try {
channel<int> out;
channel<std::string> back;
std::thread fizzbuzzing(fizzbuzzer, out, back);
for (int n = 1; n <= 100; ++n) {
out << n;
std::string result;
back >> result;
std::cout << result << "\n";
}
}
catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
server.h
#pragma once
#include <condition_variable>
#include <queue>
#include <mutex>
#include <iostream>
template<typename ValueType>
class receiving;
template<typename ValueType>
class channel {
private:
std::mutex key;
std::condition_variable_any non_empty;
std::queue<ValueType> fifo;
public:
void send(const ValueType & to_send) {
std::lock_guard<std::mutex> guard(key);
fifo.push(to_send);
non_empty.notify_all();
}
bool try_receive(ValueType & to_receive) {
bool received = false;
if (key.try_lock()) {
std::lock_guard<std::mutex> guard(key, std::adopt_lock);
if (!fifo.empty()) {
to_receive = fifo.front();
fifo.pop();
received = true;
}
}
return received;
}
void receive(ValueType & to_receive) {
std::lock_guard<std::mutex> guard(key);
non_empty.wait(
key,
[this] {
return !fifo.empty();
});
to_receive = fifo.front();
fifo.pop();
}
void operator<<(const ValueType & to_send) {
send(to_send);
}
receiving<ValueType> operator>>(ValueType & to_receive) {
return receiving(this, to_receive);
}
};
template<typename ValueType>
class receiving {
private:
channel<ValueType> * that;
ValueType & to_receive;
public:
receiving(channel<ValueType> * that, ValueType & to_receive)
: that(that), to_receive(to_receive)
{}
receiving(receiving && other)
: that(other.that), to_receive(other.to_receive)
{
other.that = nullptr;
}
operator bool() {
auto from = that;
that = nullptr;
return from && from->try_recieve(to_receive);
}
~receiving() {
if (that)
that->receive(to_receive);
}
};
I know that the code he is showing is only an example code, but I figured I would try it within my IDE while following the video to get a better understanding of his talk. I'd like to be able to compile this just to see the generated output, and to be able to step through the debugger and disassembler, but I've hit a roadblock at this point. I understand the generated compiler error, just not sure how to resolve it based on his code sample...
Here's the compiler error that is being generated:
1>------ Build started: Project: Computations, Configuration: Debug Win32 ------
1>main.cpp
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\memory(2539): error C2661: 'std::tuple<void (__cdecl *)(channel<int> &,channel<std::string> &),channel<int>,channel<std::string>>::tuple': no overloaded function takes 3 arguments
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\thread(46): note: see reference to function template instantiation 'std::unique_ptr<std::tuple<void (__cdecl *)(channel<int> &,channel<std::string> &),channel<int>,channel<std::string>>,std::default_delete<_Ty>> std::make_unique<std::tuple<void (__cdecl *)(channel<int> &,channel<std::string> &),channel<int>,channel<std::string>>,void(__cdecl &)(channel<int> &,channel<std::string> &),channel<int>&,channel<std::string>&,0>(void (__cdecl &)(channel<int> &,channel<std::string> &),channel<int> &,channel<std::string> &)' being compiled
1> with
1> [
1> _Ty=std::tuple<void (__cdecl *)(channel<int> &,channel<std::string> &),channel<int>,channel<std::string>>
1> ]
1>c:\users\skilz99\source\repos\computations\computations\main.cpp(31): note: see reference to function template instantiation 'std::thread::thread<void(__cdecl &)(channel<int> &,channel<std::string> &),channel<int>&,channel<std::string>&,void>(_Fn,channel<int> &,channel<std::string> &)' being compiled
1> with
1> [
1> _Fn=void (__cdecl &)(channel<int> &,channel<std::string> &)
1> ]
1>Done building project "Computations.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========