I've got a function like this:
void loadData(std::function<void (std::string, std::string, std::string)> callback)
{
// data loading stuff
callback(body, subject, header);
}
The problem is I'm not necessarily need to use subject and header in my callback function. Now I'm handling it this way:
loadData([](std::string body, std::string, std::string){
std::cout << body;
})
I want to replace it with
loadData([](std::string body){
std::cout << body;
})
and automatically pass to callback function as many arguments as it able to accept.
I don't want to manually overload loadData function for all 3 possible argument counts. I also don't want to use any more complicated lambda syntax on the calling site because my library should be clear for others to use.
Is this possible using C++ STL and Boost?
What about ignoring the following arguments using ... ?
loadData([](std::string body, ...){
std::cout << body;
})
As pointed by StoryTeller (thanks!) the use of ellipsis can be unsupported for non trivial types (see [expr.call]p9 for more details).
To avoid this problem, if you can use C++14, you can use auto ... (better auto && ... to avoid unnecessary copies; thanks Yakk).
loadData([](std::string body, auto && ...){
std::cout << body;
})
I got inspired by one of the other answers, which proposes to make a wrapper that passes the correct number of parameters to the functor. I find this solution very nice, and thought I would try make a general templated wrapper, where the number of arguments is not hardcoded. Here is what I came up with:
#include <string>
#include <functional>
#include <iostream>
struct WrapperHelp
{
template
< typename L
, typename Tuple
, std::size_t... Is
, typename... Ts
>
static auto apply(L&& l, Tuple t, std::index_sequence<Is...>, Ts&&... ts)
-> decltype(l(std::get<Is>(t)...))
{
return l(std::get<Is>(t)...);
}
template
< typename L
, typename Tuple
, std::size_t... Is
, typename T1
, typename... Ts
>
static auto apply(L&& l, Tuple t, std::index_sequence<Is...>, T1&& t1, Ts&&... ts)
-> decltype(WrapperHelp::apply(std::forward<L>(l), std::forward_as_tuple(std::get<Is>(t)..., t1), std::make_index_sequence<sizeof...(Is) +1 >(), ts...))
{
return WrapperHelp::apply(std::forward<L>(l), std::forward_as_tuple(std::get<Is>(t)..., t1), std::make_index_sequence<sizeof...(Is) + 1>(), ts...);
}
};
template<typename L>
struct OptionalWrapper {
public:
OptionalWrapper(L l) : lambda{std::move(l)} {}
template<typename... Ts>
void operator()(Ts&&... ts) const
{
WrapperHelp::apply(lambda, std::tuple<>(), std::index_sequence<>(), std::forward<Ts>(ts)...);
}
private:
L lambda;
};
template<typename L>
auto makeOptionalWrapper(L l) { return OptionalWrapper<L>{std::move(l)}; }
template<class F>
void loadData(OptionalWrapper<F>&& callback)
{
std::string body = "body";
std::string subject = "subject";
std::string header = "header";
double lol = 2.0;
callback(body, subject, header, lol);
}
template<typename L>
void loadData(L callback)
{
loadData(makeOptionalWrapper(std::move(callback)));
}
int main() {
//apply(std::tuple<double>(2), std::tuple<double>(2));
loadData([](auto&& body) {
std::cout << body << std::endl;
});
loadData([](auto&& body, auto&& subject) {
std::cout << body << " " << subject << std::endl;
});
loadData([](auto&& body, auto&& subject, auto&& header) {
std::cout << body << " " << subject << " " << header << std::endl;
});
loadData([](auto&& body, auto&& subject, auto&& header, auto&& lol) {
std::cout << body << " " << subject << " " << header << " " << lol << std::endl;
});
return 0;
}
This should work for any function, with any number of "optional" parameters, and with any types of parameters. It is not the prettiest code, but I hope the idea is clear and can be of some use :)
Live example
You could make a wrapper around the lambda.
template<typename L>
struct OptionalWrapper {
OptionalWrapper(L l) : lambda{std::move(l)} {}
void operator()(std::string body, std::string subject, std::string header) const {
call(lambda, body, subject, header);
}
private:
template<typename T>
auto call(T& l, std::string body, std::string subject, std::string header) const
-> decltype(l(body, subject, header))
{
return l(body, subject, header);
}
template<typename T>
auto call(T& l, std::string body, std::string subject, std::string) const
-> decltype(l(body, subject))
{
return l(body, subject);
}
template<typename T>
auto call(T& l, std::string body, std::string, std::string) const
-> decltype(l(body))
{
return l(body);
}
L lambda;
};
template<typename L>
auto makeOptionalWrapper(L l) { return OptionalWrapper<L>{std::move(l)}; }
Then, use your wrapper like that:
void loadData(std::function<void (std::string, std::string, std::string)> callback)
{
callback(body, subject, header);
}
template<typename L>
void loadData(L callback)
{
loadData({makeOptionalWrapper(std::move(callback))});
}
Related
I have a generic class, where two of the generics are going to be identical 90% of the time, but on the off chance that they are separate types, I need to perform member initialization a little bit differently.
template<typename S, typename T = S>
class MyClass {
MyClass(const Options<S> & opts) {
if (std::is_same<S,T>::value) {
thing.reset(new T(opts.get_s_thing())); // 90% of time, use type S in args to initialize thing
} else {
thing.reset(new T()); // Special case, types differ, so create a new one
}
//
// Other constructor things...
//
}
std::shared_ptr<T> thing;
};
Only thing is, since type-checking is done at compile time, the thing.reset(opts.get_s_thing()); line throws an error if I create MyClass with an explicitly different type for T. But because the types differ, that line would never get called anyways. Is there some preprocessor directive I can use here? What strategy should I take?
Changing the constructor signature in MyClass is not an option, since this is part of a VERY large codebase. T is a new thing, so I have more freedom in deciding the "standard interface" for Ts.
I would separate the two constructors. And take the rest of the current constructor code apart, e.g. to an initialize function.
[c++11] Using enable_if. [Demo]
template <typename S, typename T = S>
struct MyClass {
void initialize() {
std::cout << "initialize\n";
//
// Other constructor things...
//
}
template <typename U = S>
MyClass(const Options<typename std::enable_if<std::is_same<U,T>::value, U>::type>& opts) {
std::cout << "Same same, ";
thing.reset(new S(opts.get_s_thing()));
initialize();
}
template <typename U = S>
MyClass(const Options<typename std::enable_if<not std::is_same<U,T>::value, U>::type>& opts) {
std::cout << "But different, ";
thing.reset(new T());
initialize();
}
std::shared_ptr<T> thing;
};
[c++20] Using a requires clause. [Demo]
template <typename S, typename T = S>
struct MyClass {
void initialize()
{
std::cout << "initialize\n";
//
// Other constructor things...
//
}
MyClass(const Options<S>& opts) requires std::is_same<S,T>::value {
std::cout << "Same same, ";
thing.reset(new S(opts.get_s_thing()));
initialize();
}
MyClass(const Options<S>& opts) {
std::cout << "But different, ";
thing.reset(new T());
initialize();
}
std::shared_ptr<T> thing;
};
Other options if you want to keep the current signature completely unchanged are:
[c++11] Using partial specializations of a helper class. [Demo]
template <typename U, typename V, bool ConstructorsAreEqual>
struct MyThingInitializer;
template <typename U, typename V>
struct MyThingInitializer<U, V, true> {
static void initialize(const Options<U>& opts, std::shared_ptr<V> thing) {
std::cout << "Same same\n";
thing.reset(new V(opts.get_s_thing()));
}
};
template <typename U, typename V>
struct MyThingInitializer<U, V, false> {
static void initialize(const Options<U>&, std::shared_ptr<V> thing) {
std::cout << "But different\n";
thing.reset(new V());
}
};
MyClass(const Options<S>& opts) {
MyThingInitializer<S, T, std::is_same<S, T>::value>::initialize(opts, thing);
//
// Other constructor things...
//
}
[c++20] Using if constexpr. [Demo]
MyClass(const Options<S>& opts) {
if constexpr(std::is_same<S,T>::value)
{
std::cout << "Same same\n";
thing.reset(new S(opts.get_s_thing()));
}
else
{
std::cout << "But different";
thing.reset(new T());
}
//
// Other constructor things...
//
}
In another order of things, it's not recommended to use new with smart pointers. You may want to change your lines:
thing.reset(new S(opts.get_s_thing()));
thing.reset(new T());
for:
std::make_shared<U>(opts.get_s_thing()).swap(thing);
std::make_shared<T>().swap(thing);
Boost's program_options library now supports boost::optional, can the same be done with std::optional?
I attempted to modify both the documentation example and the code in the PR, but neither seems to work.
For example, the very simple case for integers (before trying template specializations):
void validate(boost::any& v, const std::vector<std::string>& values, std::optional<int>* target_type,
int) {
using namespace boost::program_options;
validators::check_first_occurrence(v);
const string& s = validators::get_single_string(values);
int n = lexical_cast<int>(s);
v = any(std::make_optional<int>(n));
}
fails with the error that the target type is not istreamable:
external/boost/boost/lexical_cast/detail/converter_lexical.hpp:243:13:
error: static_assert failed due to requirement
'has_right_shift<std::__1::basic_istream<char>, std::__1::optional<int>, boost::binary_op_detail::dont_care>::value || boost::has_right_shift<std::__1::basic_istream<wchar_t>, std::__1::optional<int>, boost::binary_op_detail::dont_care>::value'
"Target type is neither std::istream`able nor std::wistream`able"
The problem with things like validate (and operator>> as well) is often ADL¹.
You need to declare the overload in one of the associated namespaces. In this case, because int is a primitive type, the only associated namespaces come from library code:
std for optional, vector, string, allocator, char_traits (yes these all count!)
boost for any
You'd prefer not to add your code in those namespaces, because you might interfere with library functions or invite future breakage when the library implementation details change.
If you had to choose, you'd prefer to choose boost here, because
that's the library providing the feature at hand
the validate free function is explicitly designed to be an customization point
Sidenote: Keep an eye out for tag_invoke - a better way to build customization points in libraries
The Fix
After all this verbiage, the solution is very simple:
namespace boost {
void validate(boost::any& v, const std::vector<std::string>& values,
std::optional<int>*, int) {
using namespace boost::program_options;
validators::check_first_occurrence(v);
const std::string& s = validators::get_single_string(values);
int n = boost::lexical_cast<int>(s);
v = boost::any(std::make_optional<int>(n));
}
} // namespace boost
Adding two lines made it work: Live On Wandbox.
Other Notes:
The "solution" injecting operator>> in general is less pure
because
it has a potential to "infect" all other code with ADL-visible overloads that might interfere. Way more code uses operator>> than
boost's validate function
it thereby invites UB due to
ODR violations,
when another translation unit, potentially legitimely, defines
another operator>> for the same arguments.
On recent compilers you can say vm.contains instead of the slightly abusive vm.count
There's another snag with non-streamable types, where, if you define a default value, you probably also need to specify the string representation with it.
Listing
Compiling on Compiler Explorer
#include <boost/program_options.hpp>
#include <optional>
#include <iostream>
namespace po = boost::program_options;
namespace boost {
void validate(boost::any& v, const std::vector<std::string>& values,
std::optional<int>*, int) {
using namespace boost::program_options;
validators::check_first_occurrence(v);
const std::string& s = validators::get_single_string(values);
int n = boost::lexical_cast<int>(s);
v = boost::any(std::make_optional<int>(n));
}
} // namespace boost
int main(int ac, char* av[]) {
try {
using Value = std::optional<int>;
po::options_description desc("Allowed options");
desc.add_options()
("help", "produce help message")
("value", po::value<Value>()->default_value(10, "10"),
"value")
;
po::variables_map vm;
po::store(po::parse_command_line(ac, av, desc), vm);
po::notify(vm);
if (vm.contains("value")) {
std::cout << "value is " << vm["value"].as<Value>().value() << "\n";
}
} catch (std::exception& e) {
std::cout << e.what() << "\n";
return 1;
}
}
BONUS
As an added exercise, let's demonstrate that if your optional value_type is not a primitive, but rather your library type, declared in a namespace MyLib, then we don't have most of the trade-offs above:
namespace MyLib {
template <typename T> struct MyValue {
MyValue(T v = {}) : value(std::move(v)) {}
private:
T value;
friend std::istream& operator>>(std::istream& is, MyValue& mv) {
return is >> mv.value;
}
friend std::ostream& operator<<(std::ostream& os, MyValue const& mv) {
return os << mv.value;
}
};
Now you could provide generic validators for any types in your MyLib namespace, be it optional or not, and have ADL find them through your MyLib namespace:
template <typename T, typename Values>
void validate(boost::any& v, Values const& values, T*, int) {
po::validators::check_first_occurrence(v);
v = boost::lexical_cast<T>(
po::validators::get_single_string(values));
}
template <typename T, typename Values>
void validate(boost::any& v, Values const& values, std::optional<T>*, int) {
po::validators::check_first_occurrence(v);
v = std::make_optional(
boost::lexical_cast<T>(
po::validators::get_single_string(values)));
}
} // namespace MyLib
See Live Demo
#include <boost/program_options.hpp>
#include <iostream>
#include <iomanip>
namespace po = boost::program_options;
namespace MyLib {
template <typename T> struct MyValue {
MyValue(T v = {}) : value(std::move(v)) {}
private:
T value;
friend std::istream& operator>>(std::istream& is, MyValue& mv) {
return is >> std::boolalpha >> mv.value;
}
friend std::ostream& operator<<(std::ostream& os, MyValue const& mv) {
return os << std::boolalpha << mv.value;
}
};
// Provide generic validators for any types in your MyLib namespace, be it
// optional or not
template <typename T, typename Values>
void validate(boost::any& v, Values const& values, T*, int) {
po::validators::check_first_occurrence(v);
v = boost::lexical_cast<T>(
po::validators::get_single_string(values));
}
template <typename T, typename Values>
void validate(boost::any& v, Values const& values, std::optional<T>*, int) {
po::validators::check_first_occurrence(v);
v = std::make_optional(
boost::lexical_cast<T>(
po::validators::get_single_string(values)));
}
} // namespace MyLib
int main(int ac, char* av[]) {
try {
using Int = MyLib::MyValue<int>;
using OptInt = std::optional<MyLib::MyValue<int>>;
using OptStr = std::optional<MyLib::MyValue<std::string> >;
po::options_description desc("Allowed options");
desc.add_options()
("ival", po::value<Int>()->default_value(Int{10}),
"integer value")
("opti", po::value<OptInt>()->default_value(OptInt{}, "(nullopt)"),
"optional integer value")
("sval", po::value<OptStr>()->default_value(OptStr{"secret"}, "'secret'"),
"optional string value")
;
po::variables_map vm;
po::store(po::parse_command_line(ac, av, desc), vm);
po::notify(vm);
std::cout << "Options: " << desc << "\n";
if (vm.contains("ival")) {
std::cout << "ival is " << vm["ival"].as<Int>() << "\n";
}
if (vm.contains("opti")) {
if (auto& v = vm["opti"].as<OptInt>())
std::cout << "opti is " << v.value() << "\n";
else
std::cout << "opti is nullopt\n";
}
if (vm.contains("sval")) {
if (auto& v = vm["sval"].as<OptStr>())
std::cout << "sval is " << v.value() << "\n";
else
std::cout << "sval is nullopt\n";
}
} catch (std::exception& e) {
std::cout << e.what() << "\n";
return 1;
}
}
For ./a.out --ival=42 --sval=LtUaE prints:
Options: Allowed options:
--ival arg (=10) integer value
--opti arg (=(nullopt)) optional integer value
--sval arg (='secret') optional string value
ival is 42
opti is nullopt
sval is LtUaE
¹ see also See also Why Does Boost Use a Global Function Override to Implement Custom Validators in "Program Options"
A parser application where I’m working on calls for recursive rules. Besides looking into the Recursive AST tutorial examples of Boost Spirit X3 which can be found here:
https://www.boost.org/doc/libs/develop/libs/spirit/doc/x3/html/index.html, I was looking for a solution with a std::variant of some types as well as a std::vector of that same
variant type.
In the StackOverflow post titled: Recursive rule in Spirit.X3, I found the code from the answer from sehe a decent starting point for my parser.
I have repeated the code here but I have limited the input strings to be tested. Because the full list from the original is not relevant for this question here.
//#define BOOST_SPIRIT_X3_DEBUG
#include <iostream>
#include <boost/fusion/adapted.hpp>
#include <boost/spirit/home/x3.hpp>
#include <string>
#include <vector>
#include <variant>
struct value: std::variant<int,float,std::vector<value>>
{
using base_type = std::variant<int,float,std::vector<value>>;
using base_type::variant;
friend std::ostream& operator<<(std::ostream& os, base_type const& v) {
struct {
std::ostream& operator()(float const& f) const { return _os << "float:" << f; }
std::ostream& operator()(int const& i) const { return _os << "int:" << i; }
std::ostream& operator()(std::vector<value> const& v) const {
_os << "tuple: [";
for (auto& el : v) _os << el << ",";
return _os << ']';
}
std::ostream& _os;
} vis { os };
return std::visit(vis, v);
}
};
namespace parser {
namespace x3 = boost::spirit::x3;
x3::rule<struct value_class, value> const value_ = "value";
x3::rule<struct o_tuple_class, std::vector<value> > o_tuple_ = "tuple";
x3::real_parser<float, x3::strict_real_policies<float> > float_;
const auto o_tuple__def = "tuple" >> x3::lit(':') >> ("[" >> value_ % "," >> "]");
const auto value__def
= "float" >> (':' >> float_)
| "int" >> (':' >> x3::int_)
| o_tuple_
;
BOOST_SPIRIT_DEFINE(value_, o_tuple_)
const auto entry_point = x3::skip(x3::space) [ value_ ];
}
int main()
{
for (std::string const str : {
"float: 3.14",
"int: 3",
"tuple: [float: 3.14,int: 3]",
"tuple: [float: 3.14,int: 3,tuple: [float: 4.14,int: 4]]"
}) {
std::cout << "============ '" << str << "'\n";
//using boost::spirit::x3::parse;
auto first = str.begin(), last = str.end();
value val;
if (parse(first, last, parser::entry_point, val))
std::cout << "Parsed '" << val << "'\n";
else
std::cout << "Parse failed\n";
if (first != last)
std::cout << "Remaining input: '" << std::string(first, last) << "'\n";
}
}
However I would like to use a traditional visitor class rather than making ostream a friend in the variant class. You know just a struct/class with a bunch of function objects for each type you encounter in the variant and a "for loop" for the vector that calls std::visit for each
element.
My goal for the traditional visitor class is to be able to maintain a state machine during printing.
My own attempts to write this visitor class did fail because I ran into an issue with my GCC 8.1 compiler. With GCC during compilation std::variant happens to be std::variant_size somehow and I got the following error:
error: incomplete type 'std::variant_size' used in nested name specifier
More about this here:
Using std::visit on a class inheriting from std::variant - libstdc++ vs libc++
Is it possible giving this constraint on GCC to write a visitor class for the code example I included, so that the ostream stuff can be removed?
Is it possible giving this constraint on GCC to write a visitor class for the code example I included, so that the ostream stuff can be removed?
Sure. Basically, I see three approaches:
1. Add the template machinery
You can specialize the implementation details accidentally required by GCC:
struct value: std::variant<int,float,std::vector<value>> {
using base_type = std::variant<int,float,std::vector<value>>;
using base_type::variant;
};
namespace std {
template <> struct variant_size<value> :
std::variant_size<value::base_type> {};
template <size_t I> struct variant_alternative<I, value> :
std::variant_alternative<I, value::base_type> {};
}
See it live on Wandbox (GCC 8.1)
2. Don't (again live)
Extending the std namespace is fraught (though I think it's legal for
user-defined types). So, you can employ my favorite pattern and hide th
estd::visit dispatch in the function object itself:
template <typename... El>
void operator()(std::variant<El...> const& v) const { std::visit(*this, v); }
Now you can simply call the functor and it will automatically dispatch
on your own variant-derived type because that operator() overload does
NOT have the problems that GCC stdlib has:
if (parse(first, last, parser::entry_point, val))
{
display_visitor display { std::cout };
std::cout << "Parsed '";
display(val);
std::cout << "'\n";
}
3. Make things explicit
I like this the least, but it does have merit: there's no magic and no
tricks:
struct value: std::variant<int,float,std::vector<value>> {
using base_type = std::variant<int,float,std::vector<value>>;
using base_type::variant;
base_type const& as_variant() const { return *this; }
base_type& as_variant() { return *this; }
};
struct display_visitor {
void operator()(value const& v) const { std::visit(*this, v.as_variant()); }
// ...
Again, live
SUMMARY
After thinking a bit more, I'd recommend the last approach, due to the relative simplicity. Clever is often a code-smell :)
Full listing for future visitors:
//#define BOOST_SPIRIT_X3_DEBUG
#include <iostream>
#include <boost/fusion/adapted.hpp>
#include <boost/spirit/home/x3.hpp>
#include <string>
#include <vector>
#include <variant>
struct value: std::variant<int,float,std::vector<value>> {
using base_type = std::variant<int,float,std::vector<value>>;
using base_type::variant;
base_type const& as_variant() const { return *this; }
base_type& as_variant() { return *this; }
};
struct display_visitor {
std::ostream& _os;
void operator()(value const& v) const { std::visit(*this, v.as_variant()); }
void operator()(float const& f) const { _os << "float:" << f; }
void operator()(int const& i) const { _os << "int:" << i; }
void operator()(std::vector<value> const& v) const {
_os << "tuple: [";
for (auto& el : v) {
operator()(el);
_os << ",";
}
_os << ']';
}
};
namespace parser {
namespace x3 = boost::spirit::x3;
x3::rule<struct value_class, value> const value_ = "value";
x3::rule<struct o_tuple_class, std::vector<value> > o_tuple_ = "tuple";
x3::real_parser<float, x3::strict_real_policies<float> > float_;
const auto o_tuple__def = "tuple" >> x3::lit(':') >> ("[" >> value_ % "," >> "]");
const auto value__def
= "float" >> (':' >> float_)
| "int" >> (':' >> x3::int_)
| o_tuple_
;
BOOST_SPIRIT_DEFINE(value_, o_tuple_)
const auto entry_point = x3::skip(x3::space) [ value_ ];
}
int main()
{
for (std::string const str : {
"float: 3.14",
"int: 3",
"tuple: [float: 3.14,int: 3]",
"tuple: [float: 3.14,int: 3,tuple: [float: 4.14,int: 4]]"
}) {
std::cout << "============ '" << str << "'\n";
//using boost::spirit::x3::parse;
auto first = str.begin(), last = str.end();
value val;
if (parse(first, last, parser::entry_point, val))
{
display_visitor display { std::cout };
std::cout << "Parsed '";
display(val);
std::cout << "'\n";
}
else
std::cout << "Parse failed\n";
if (first != last)
std::cout << "Remaining input: '" << std::string(first, last) << "'\n";
}
}
I have a method that takes an index-able object as a template parameter, something like:
template <typename OBJ>
int foo(int n, OBJ o)
{
int x = 0;
for (int i = 0; i < n; ++i) {
x += o[i];
}
return x;
}
Is there a way I can pass a lambda function in for the o parameter? In other words, having the lambda be call-able via the [] operator rather than the () operator?
template<class F>
struct square_bracket_invoke_t {
F f;
template<class T>
auto operator[](T&& t)const
-> typename std::result_of< F const&(T&&) >::type
{ return f(std::forward<T>(t)); }
};
template<class F>
square_bracket_invoke_t< typename std::decay<F>::type >
make_square_bracket_invoke( F&& f ) {
return {std::forward<F>(f)};
}
Live example.
Code is C++11 and has basically zero overhead.
int main() {
std::cout << foo( 6, make_square_bracket_invoke([](int x){ return x; } ) ) << "\n";
}
result is 0+1+2+3+4+5 aka 15.
Is this a good idea? Maybe. But why stop there?
For max amusement:
const auto idx_is = make_square_bracket_invoke([](auto&&f){return make_square_bracket_invoke(decltype(f)(f));});
int main() {
std::cout << foo( 6, idx_is[[](int x){ return x; }] ) << "\n";
}
You can do that by:
Creating a class template, a functor, that has the operator[] defined.
Implementing the operator[] in terms of the operator() of a std::function.
Storing the lambda in a wrapped std::function as a member variable of the class template.
Here's a demonstrative program.
#include <iostream>
#include <functional>
template <typename OBJ>
int foo(int n, OBJ o)
{
int x = 0;
for (int i = 0; i < n; ++i) {
x += o[i];
}
return x;
}
template <typename> struct Functor;
template <typename R> struct Functor<R(int)>
{
using ftype = std::function<R(int)>;
Functor(ftype f) : f_(f) {}
R operator[](int i) const { return f_(i); }
ftype f_;
};
int main()
{
Functor<int(int)> f = {[](int i) -> int {return i*i;}};
std::cout << foo(10, f) << std::endl;
}
and its output
285
Live demo
PS
Functor is not the appropriate name here. It does not overload the function call operator. I suspect there is a more appropriate name.
Well, if it helps, here's a way to forward a wrapper class's operator[] to your lambda's operator().
template<class F>
struct SubscriptWrapper_t {
F f_;
template<class T> auto operator[](T const& t_) const -> decltype(f_(t_)) {
return f_(t_);
}
};
template<class F>
SubscriptWrapper_t<typename std::decay<F>::type> SubscriptWrapper(F&& f_) {
return{std::forward<F>(f_)};
}
I use wrappers like this a lot. They're convenient, and they don't seem to have any computational overhead, at least when compiled by GCC. You can make one for at or even make one for find.
EDIT: Updated for C++11 (and updated to be able to return a reference)
A sketch of a wrapper type that would do this.
template<typename UnaryFunction>
class index_wrapper
{
public:
index_wrapper(UnaryFunction func) : func(std::move(func)) {}
template<typename T>
std::invoke_result_t<UnaryFunction, T> operator[](T&& t)
{ return func(std::forward<T>(t)); }
private:
UnaryFunction func;
};
With usage
#include <iostream>
template <typename OBJ>
int foo(int n, OBJ o)
{
int x = 0;
for (int i = 0; i < n; ++i) {
x += o[i];
}
return x;
}
int main()
{
index_wrapper f([](int i) -> int { return i*i; });
std::cout << foo(10, f) << std::endl;
}
You might want to restrict it to a single parameter type, so that you can provide member type aliases similar to std::vector::reference et.al.
https://stackoverflow.com/a/31860104
#include <iostream>
#include <string>
template<class T>
auto optionalToString(T* obj)
-> decltype( obj->toString() )
{
return obj->toString();
}
auto optionalToString(...) -> std::string
{
return "toString not defined";
}
struct TA
{
std::string toString() const
{
return "Hello";
}
};
struct TB
{
};
Question> Given the proposed solution optionalToString, how I can use it to detect that TA has toString while TB doesn't.
A solution using can_apply from this code:
template<class T>
using toString_result = decltype(std::declval<T>().toString());
template<class T>
constexpr auto has_toString = can_apply<toString_result, T>::value;
Used like this:
struct TA
{
std::string toString() const
{
return "Hello";
}
};
struct TB
{
};
int main()
{
std::cout << has_toString<TA> << '\n';
std::cout << has_toString<TB> << '\n';
return 0;
}
DEMO
The given solution allows you to always get a string from any object. If it has a toString() member function, this will be used, otherwise, a default string. Usage example, given the above:
TA a;
TB b;
std::cout << "a: " << optionalToString(&a) << '\n';
std::cout << "b: " << optionalToString(&b) << std::endl;
However, you will not get a boolean value whether a or b has a toString() method. If you want that, you need something like the solution proposed by O'Neil.