Я следил за выступлением на YouTube Кельвина Хенни, основанного на идиоме функционального С++... Примерно через 50 минут видео он начинает показывать пример структуры класса, которую он назвал channel
. Затем он пишет простую функцию fizzbuzz
и собирается передать ее серверу как кусок кода, используя потоки. Я использую код из его видео, которое можно найти здесь: Kevlin Henney - Functional C++ а>
Однако, когда я пытаюсь скомпилировать программу, Visual Studio генерирует ошибку компилятора C2661
, указывающую на std::tuple
..., которая исходит от конструктора std::tread
в моем коде.
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;
}
сервер.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);
}
};
Я знаю, что код, который он показывает, является лишь примером кода, но я решил попробовать его в своей IDE, следя за видео, чтобы лучше понять его речь. Я хотел бы иметь возможность скомпилировать это только для того, чтобы увидеть сгенерированный вывод и иметь возможность пройти через отладчик и дизассемблер, но на этом этапе я столкнулся с препятствием. Я понимаю сгенерированную ошибку компилятора, просто не уверен, как ее решить на основе его примера кода...
Вот ошибка компилятора, которая генерируется:
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 ==========
mutex
, но это дерьмовое сообщение об ошибке. - person user4581301   schedule 28.06.2020std::unique_ptr
тоже появляется в сгенерированной ошибке компилятора ... иstd::unique_ptr
не подлежит копированию, если я правильно помню, в отличие отstd::shared_ptr
... но это не должно иметь ничего общего с не разрешая 3 аргумента... тогда опять же это может... - person Francis Cugler   schedule 28.06.2020thread
принимают параметры по значению, и вы не можете скопироватьmutex
илиcondition_variable
, так что это ошибка, но я не понимаю, как это влияет на ошибку, которую вы видите. - person user4581301   schedule 28.06.2020channel
копируемым или пройдете это по ссылке, но это одно серьезно непостижимое сообщение об ошибке. - person user4581301   schedule 28.06.2020std::ref
избавило от ошибки компилятора. Я могу скомпилировать и запустить программу... Однако она не свободна от ошибок после того, как99
,Fizz
,Buzz
напечатаны, отладчик вызывает ошибку отладки, указывающую, чтоabort()
был вызван, и приложение завершает работу с кодом ошибки3
... Но, как я уже сказал, это всего лишьsample
код, так что ничего страшного! - person Francis Cugler   schedule 28.06.2020