Reputation: 2594
I'm trying to compile this code:
#include <functional>
#include <string>
#include <iostream>
namespace outcome {
//// Class c_out (T)
template <class T = void>
class c_out {
public:
bool success = false;
std::string error = "";
T result;
// Then
template<typename Func, typename... Args>
c_out<T> then(Func&& func, Args&&... args) const {
if (success) {
return std::forward<Func>(func)(std::forward<Args>(args)...);
} else {
return *this;
};
};
// Error handler
template<typename Func, typename... Args>
c_out<T> except(Func&& func, Args&&... args) const {
if (!success) {
return std::forward<Func>(func)(result, error, std::forward<Args>(args)...);
};
return *this;
};
};
//// Class c_out (void)
template <>
class c_out<void> {
public:
bool success = false;
std::string error = "";
// Then
template<typename Func, typename... Args>
c_out<void> then(Func&& func, Args&&... args) const {
if (success) {
return std::forward<Func>(func)(std::forward<Args>(args)...);
} else {
return *this;
};
};
// Error handler
template<typename Func, typename... Args>
c_out<void> except(Func&& func, Args&&... args) const {
if (!success) {
return std::forward<Func>(func)(error, std::forward<Args>(args)...);
};
return *this;
};
};
//// Run (void)
template<typename Func, typename... Args>
c_out<void> run(Func&& func, Args&&... args) {
return std::forward<Func>(func)(std::forward<Args>(args)...);
};
//// Failed
template <class T>
c_out<T> failed(T res, const std::string& error_msg) {
c_out<T> outcome;
outcome.success = false;
outcome.error = error_msg;
return outcome;
};
//// Failed (void)
c_out<void> failed(const std::string& error_msg) {
c_out<void> outcome;
outcome.success = false;
outcome.error = error_msg;
return outcome;
};
};
int main(void) {
auto log_message = [](const std::string& msg) {
std::cout<<msg<<std::endl;
return outcome::c_out<>();
};
outcome::c_out<> out = outcome::run(log_message, "XXX").then(log_message, "YYY").except(outcome::failed);
return 0;
}
However, I get this error:
<source>: In function 'int main()':
<source>:92:108: error: no matching function for call to 'outcome::c_out<void>::except(<unresolved overloaded function type>)'
92 | outcome::c_out<> out = outcome::run(log_message, "XXX").then(log_message, "YYY").except(outcome::failed);
| ^
<source>:54:25: note: candidate: 'template<class Func, class ... Args> outcome::c_out<void> outcome::c_out<void>::except(Func&&, Args&& ...) const'
54 | c_out<void> except(Func&& func, Args&&... args) const {
| ^~~~~~
<source>:54:25: note: template argument deduction/substitution failed:
<source>:92:108: note: couldn't deduce template parameter 'Func'
92 | outcome::c_out<> out = outcome::run(log_message, "XXX").then(log_message, "YYY").except(outcome::failed);
|
Why? How can I solve the template argument deduction error?
Upvotes: 0
Views: 63
Reputation: 141910
One way is to the same you did with c_out
:
//// Failed
template <class T = void>
struct failed {
c_out<T> operator() (const std::string& error_msg, T res) {
c_out<T> outcome;
outcome.success = false;
outcome.error = error_msg;
return outcome;
}
};
template <>
struct failed<void> {
c_out<void> operator() (const std::string& error_msg) {
c_out<void> outcome;
outcome.success = false;
outcome.error = error_msg;
return outcome;
}
};
but then a bit more ugly:
..........except(outcome::failed<>());
Upvotes: 0
Reputation: 275896
failed
is not a function, failed
is an overload set. You cannot name an overload set and pass it as an argument to a template and deduce a single function type.
[](auto&&...args)->decltype(auto){return outcome::failed(decltype(args)(args)...);}
is a 95% compatible function object that dispatches to the overload set of failed
.
There are many other ways to solve this as well.
Upvotes: 2