Turn casting / construction into a perfect forwardable function - c++

SSCCE:
#include <functional>
using std::function;
using std::forward;
template<typename ToType, typename... FromTypes>
ToType construct(FromTypes&&... fromTypes) {
return ToType(forward<FromTypes>(fromTypes)...);
}
class Maybe {
public:
Maybe() : m_value(42.0f) {}
template<typename Function>
auto apply(Function function) const -> decltype(function(std::declval<float>())) {
return function(value());
}
private:
float const& value() const {
return m_value;
}
float m_value;
};
int main() {
Maybe a;
a.apply(construct<int, float>);
return 0;
}
Gives the error:
test.cpp: In instantiation of ‘decltype (function(declval<float>())) Maybe::apply(Function) const [with Function = int (*)(float&&); decltype (function(declval<float>())) = int]’:
test.cpp:31:32: required from here
test.cpp:17:28: error: invalid initialization of reference of type ‘float&&’ from expression of type ‘const float’
return function(value());
^
From the error message, it's obviously a problem with the fact that value() returns a const&.
The key point here, is that the type isn't being deduced on line 17, where value is being passed to it. The type is being assigned when the construct function is passed to apply on line 31.
I specified the wrong type to the template of construct. construct<int, float>. If I use construct<int, float const&> it functions just fine.
However, this is cumbersome and requires knowledge of the implementation of apply. And it will also never ever bind an lvalue, because T and T&& are different types. (Because of the lack of type deduction.)
Is there a way to have a function I can pass to another function and have type deduction occur at the site where it is called, so I can have perfect forwarding happen more or less transparently for the callers? Or is there another way to achieve this end that doesn't leak complexity to the caller?

How about this?
#include <functional>
using std::function;
using std::forward;
template<typename ToType>
class construct
{
public:
template<typename... FromTypes>
ToType operator()(FromTypes&&... fromTypes) {
return ToType(forward<FromTypes>(fromTypes)...);
}
};
class Maybe {
public:
Maybe() : m_value(42.0f) {}
template<typename Function>
auto apply(Function function) const -> decltype(function(std::declval<float>())) {
return function(value());
}
private:
float const& value() const {
return m_value;
}
float m_value;
};
int main() {
Maybe a;
a.apply(construct<int>());
return 0;
}
You only have to specify the type to which you want to convert to which obviously cannot be deduced in the context you have given.

Related

Why does my concept not work if specifying two requirements [duplicate]

This question already has answers here:
Why does this compiler warning only show for int but not for string? "type qualifiers ignored on function return type"
(4 answers)
Closed 8 months ago.
I have the following code:
#include <concepts>
#include <functional>
#include <iostream>
template<typename T>
concept OperatorLike = requires(T t, const std::string s) {
{ t.get_string(s) } -> std::same_as<const std::string>;
{ t.get_int(s) } -> std::same_as<const int>;
};
template<typename T, typename O>
concept Gettable = requires(T t, O op) {
t.apply_get(0, op);
t.apply_post(0, op); };
template<std::semiregular F>
class RestApiImpl {
F m_get_method;
public:
RestApiImpl(F get = F{}) : m_get_method{std::move(get)} {}
void register_get(F functor) {
m_get_method = std::move(functor);
}
template<OperatorLike IF>
requires std::invocable<F, const int, IF>
void apply_get(const int req, IF interface){
m_get_method(req, std::move(interface));
}
template<OperatorLike IF>
requires std::invocable<F, const int, IF>
void apply_post(const int req, IF interface){
m_get_method(req, std::move(interface));
}
};
class ASpecificJSONLibrary{
public:
std::string operator[](std::string key){
return key + "_withLambda";
}
};
class Server{
public:
ASpecificJSONLibrary libObj; // this is a
struct impl;
void run(Gettable<impl> auto& api){
api.apply_get(0, impl(*this));
}
struct impl {
public:
Server& m_server;
impl(Server& server ) : m_server(server){}
const std::string get_string(const std::string key) {
return (m_server.libObj)[key];
};
const int get_int(std::string const key) {
return 1;
}
};
};
int main(){
auto get = [](int, OperatorLike auto intf){
std::string dummy = "dummy";
std::cout << intf.get_string(dummy);
};
RestApiImpl api(get);
Server server;
server.run(api);
return 0;
};
If remove the line t.get_int(s) } -> std::same_as<int>; from the concept OperatorLike everything seems to work as it should. I am not sure why adding this additional requirement gives me a compile error. The compile error also refers only to the fact that the there is no matching function to the run method, which is because the Gettable concept is not satisfied. But the root cause looks like it is the OperatorLike concept
Another observation just made is that if I remove all the consts from the operatorLike concept it all just seem to work including the additional requirements
The compound requirement
{ t.get_int(s) } -> std::same_as<const int>;
tests whether decltype((t.get_int(s))) is the same as const int. However, that is a pointless test, because there are no const prvalues of non-class type and these would be the only expressions for which decltype could result in const int.
A prvalue of non-class type will always have its const stripped. So even if get_int is declared to return const int, the type of the call expression t.get_int(s) will always be int, not const int.
In general having top-level const on a return type is almost always useless. The only use case I can think of is a class type return value for which you want to disallow calling non-const member functions without storing in a variable first, but there are better ways of achieving that (e.g. &-qualified member functions).

How can I make C++ infer template type parameters from a lambda?

This is my code:
#include<iostream>
struct Item {
int val;
};
struct XItem {
int val;
};
void transform(const Item &i, XItem &target) {
target.val = i.val;
}
template<typename T>
void show(const T &v) {
std::cout << v.val << std::endl;
}
template<typename ParamsType, typename ResultType>
void handleRequest(Item &cur, ResultType (*impl)(const ParamsType &p)) {
ParamsType p{};
transform(cur, p);
ResultType res = (*impl)(p);
show(res);
}
struct ResItem {
int val;
};
int main(int argc, char *argv[]) {
Item i{42};
handleRequest(i, [](const XItem &x) {
return ResItem{x.val};
});
return 0;
}
Compiling it gives the following error:
test.cpp:33:3: error: no matching function for call to 'handleRequest'
handleRequest(i, [](const XItem &x) {
^~~~~~~~~~~~~
test.cpp:21:6: note: candidate template ignored: could not match 'ResultType
(*)(const ParamsType &)' against '(lambda at test.cpp:33:20)'
void handleRequest(Item &cur, ResultType (*impl)(const ParamsType &p)) {
^
I am unsure why this happens, however I do suspect that because the lambda, while being implicitly convertible to a function pointer, isn't one, the template parameters can't be deduced from it.
I tried using std::function<ResultType(const ParamsType &p)> instead, which also doesn't work. This question details the problem, so I tried to use its solution:
template<typename ParamsType, typename ResultType, typename Callback>
void handleRequest(Item &cur, Callback cb) {
ParamsType p = transform(cur);
ResultType res = std::invoke(cb, p);
show(res);
}
However, now ParamsType and ResultType cannot be implicitly deduced from the callback, I would need to give them explicitly. But I really want to infer ResultType because in the actual code, it can be quite lengthy (it is inferred from the lambda return statement, which is more complex than in this minimal example). I need the two types because both transform and show are overloaded and need the types to bind.
Is it possible to have handleRequest infer those types in this scenario and if so, how?
The problem is, implicit conversion (from lambda to function pointer) is not considered in template argument deduction, which fails deducing the template parameters.
Type deduction does not consider implicit conversions (other than type adjustments listed above): that's the job for overload resolution, which happens later.
You can specify the template arguments explicitly to bypass the deduction,
handleRequest<XItem, ResItem>(i, [](const XItem &x) {
return ResItem{x.val};
});
Or convert the lambda to function pointer explicitly,
handleRequest(i, static_cast<RestItem(*)(const XItem&)>([](const XItem &x) {
return ResItem{x.val};
}));
Or use the operator+ to convert the lambda to function pointer.
handleRequest(i, +[](const XItem &x) {
return ResItem{x.val};
});

Passing function as template argument to a member function

I am trying to pass function as template argument to a function in a class, but there is some mistake. The code is giving an error error: missing template arguments before 'obj'. How can I fix this so that it compiles?
#include<iostream>
double sum_fun(const double &a, const double &b)
{ std::cout<<a+b<<"\n"; }
template <typename F>
class B
{
public:
void fb()(F f1)
{
f1(10.1,10.2);
}
};
int main()
{
B obj(sum_fun); //error
obj.fb(); //error
return 0;
}
There is a misunderstanding of how classes work.
int main()
{
B obj(sum_fun); // calls B constructor with parameter `sum_fun`
obj.fb(); // calls member function B::fb() with no parameters
return 0;
}
Both lines raise an error as
Your class has no constructor which takes a single parameter.
void fb()(F f1) is illegal syntax. To declare a member function, use only one set of parentheses: either void fb() or void fb(F f1). The latter is incorrect in our case, as your member function call obj.fb() passes no parameters.
To fix this, write up a constructor, store the function as a member variable, and use that variable in the function fb().
template <typename F>
class B
{
public:
// constructor, initialises member `m_func` through member initialisation
B(F func) : m_func(func) {}
void fb()
{
m_func(10.1,10.2);
}
private:
F m_func;
};
In C++17, thanks to automatic template deduction, no errors are now emitted. But in lower standards (e.g. C++11), template deduction is lacking and thus, the full templated type needs to be specified when declaring obj.
So in standards below C++17, the main function should be:
int main()
{
// C++11: using a function pointer to denote type
B<double(*)(const double&, const double&)> obj(sum_fun);
// ok in C++17, looks cleaner too
// B obj(sum_fun);
obj.fb();
return 0;
}
Here, double(*)(const double&, const double&) is a function pointer, i.e. a pointer to a function which returns a double and takes two parameters, both of type const double&. Function pointers may be considered as a type, which satisfies the template (template<typename F>).
Just like we do std::vector<int> and std::vector<double>, we can also do std::vector<double(*)(const double&, const double&)> to denote a vector of functions returning double and taking const double& as parameters.
And by the way, sum_fun also raises a warning: nothing is returned even though the return type is double... better specify void as the return type instead.
C++11 Demo
C++17 Demo
Is it possible to pass function as argument directly to B::fb() instead of creating constructor B::B(F) and storing in local variable?
Certainly.
#include <iostream>
void sum_fun(const double& a, const double& b)
{
std::cout << a+b << "\n";
}
template <typename F>
class B
{
public:
void fb(F func)
{
func(10.1,10.2);
}
};
int main()
{
B<void(*)(const double&, const double&)> obj;
obj.fb(sum_fun);
return 0;
}
Note that the member function fb now takes a single parameter func, which we then call. Note also that in C++17, we now can't instantiate the obj with B obj; because this would be ambiguous and the template can't be deduced automatically. Instead, we need to specify the full type B<void(*)(const double&, const double&)>.
However, a recommended alternative over function pointers is to use std::function, which is more versatile and offers a more readable syntax. (std::function Demo)
In C++17 you're allowed to use auto in template paramter list:
template <auto F>
class B
{
public:
void fb()
{
F(10.1,10.2);
}
};
You can then do B<sum_fun>:
int main()
{
B<sum_fun> obj{};
obj.fb();
return 0;
}

Given the following, what type is "function"?

Given the following, what type is "function"?
#include <functional>
#include <vector>
template<class T>
class Foo
{
public:
template<typename P, typename Q, typename R, typename... Args>
void Attach(P (Q::*f)(Args...), R p)
{
auto function = [p, f](Args... args)
{
(*p.*f)(args...);
};
Listeners.push_back(function);
}
private:
std::vector<std::function<T>> Listeners;
};
class Bar
{
public:
int Handler(int x, int y, int z)
{
return 0;
}
};
int main(void)
{
auto foo = Foo<int(int, int, int)>();
auto bar = Bar();
foo.Attach(&Bar::Handler, &bar);
}
For some context I'm attempting to make a lambda that calls a method on an instance, storing that lambda into a collection. My push_back fails to compile, with the following error:
xrefwrap(283): error C2440: 'return' : cannot convert from 'void' to
'int'
I was originally using std::bind to make a std::function that I could store. Apparently I may be able to do it with a lambda (and variadic templates, so I don't need one template per arity) but so far it's defeating me.
When you have constructed Foo, the explicit template argument supplied is auto foo = Foo<int(int, int, int)>();,
int main(void)
{
auto foo = Foo<int(int, int, int)>(); //<<<< Here is the template arguments when constructing Foo
auto bar = Bar();
foo.Attach(&Bar::Handler, &bar);
}
where as when you are registering the listener the function signatures return type is void
auto function = [p, f](Args... args)
{
(*p.*f)(args...);
};
Resolution
So either you
change the explicit template argument of Foo, auto foo = Foo<void(int, int, int)>(); to return void to match your listener callback.
or ensure that your listener function returns an integer. return (*p.*f)(args...);
Note May be you intended to return a status code from the listener but you might have missed? So the second resolution point looks to me an obvious plausible issue

How do I avoid implicit conversions on non-constructing functions?

How do I avoid implicit casting on non-constructing functions?
I have a function that takes an integer as a parameter,
but that function will also take characters, bools, and longs.
I believe it does this by implicitly casting them.
How can I avoid this so that the function only accepts parameters of a matching type, and will refuse to compile otherwise?
There is a keyword "explicit" but it does not work on non-constructing functions. :\
what do I do?
The following program compiles, although I'd like it not to:
#include <cstdlib>
//the function signature requires an int
void function(int i);
int main(){
int i{5};
function(i); //<- this is acceptable
char c{'a'};
function(c); //<- I would NOT like this to compile
return EXIT_SUCCESS;
}
void function(int i){return;}
*please be sure to point out any misuse of terminology and assumptions
Define function template which matches all other types:
void function(int); // this will be selected for int only
template <class T>
void function(T) = delete; // C++11
This is because non-template functions with direct matching are always considered first. Then the function template with direct match are considered - so never function<int> will be used. But for anything else, like char, function<char> will be used - and this gives your compilation errrors:
void function(int) {}
template <class T>
void function(T) = delete; // C++11
int main() {
function(1);
function(char(1)); // line 12
}
ERRORS:
prog.cpp: In function 'int main()':
prog.cpp:4:6: error: deleted function 'void function(T) [with T = char]'
prog.cpp:12:20: error: used here
This is C++03 way:
// because this ugly code will give you compilation error for all other types
class DeleteOverload
{
private:
DeleteOverload(void*);
};
template <class T>
void function(T a, DeleteOverload = 0);
void function(int a)
{}
You can't directly, because a char automatically gets promoted to int.
You can resort to a trick though: create a function that takes a char as parameter and don't implement it. It will compile, but you'll get a linker error:
void function(int i)
{
}
void function(char i);
//or, in C++11
void function(char i) = delete;
Calling the function with a char parameter will break the build.
See http://ideone.com/2SRdM
Terminology: non-construcing functions? Do you mean a function that is not a constructor?
8 years later (PRE-C++20, see edit):
The most modern solution, if you don't mind template functions -which you may mind-, is to use a templated function with std::enable_if and std::is_same.
Namely:
// Where we want to only take int
template <class T, std::enable_if_t<std::is_same_v<T,int>,bool> = false>
void func(T x) {
}
EDIT (c++20)
I've recently switched to c++20 and I believe that there is a better way. If your team or you don't use c++20, or are not familiar with the new concepts library, do not use this. This is much nicer and the intended method as outlines in the new c++20 standard, and by the writers of the new feature (read a papers written by Bjarne Stroustrup here.
template <class T>
requires std::same_as(T,int)
void func(T x) {
//...
}
Small Edit (different pattern for concepts)
The following is a much better way, because it explains your reason, to have an explicit int. If you are doing this frequently, and would like a good pattern, I would do the following:
template <class T>
concept explicit_int = std::same_as<T,int>;
template <explicit_int T>
void func(T x) {
}
Small edit 2 (the last I promise)
Also a way to accomplish this possibility:
template <class T>
concept explicit_int = std::same_as<T,int>;
void func(explicit_int auto x) {
}
Here's a general solution that causes an error at compile time if function is called with anything but an int
template <typename T>
struct is_int { static const bool value = false; };
template <>
struct is_int<int> { static const bool value = true; };
template <typename T>
void function(T i) {
static_assert(is_int<T>::value, "argument is not int");
return;
}
int main() {
int i = 5;
char c = 'a';
function(i);
//function(c);
return 0;
}
It works by allowing any type for the argument to function but using is_int as a type-level predicate. The generic implementation of is_int has a false value but the explicit specialization for the int type has value true so that the static assert guarantees that the argument has exactly type int otherwise there is a compile error.
Maybe you can use a struct to make the second function private:
#include <cstdlib>
struct NoCast {
static void function(int i);
private:
static void function(char c);
};
int main(){
int i(5);
NoCast::function(i); //<- this is acceptable
char c('a');
NoCast::function(c); //<- Error
return EXIT_SUCCESS;
}
void NoCast::function(int i){return;}
This won't compile:
prog.cpp: In function ‘int main()’:
prog.cpp:7: error: ‘static void NoCast::function(char)’ is private
prog.cpp:16: error: within this context
For C++14 (and I believe C++11), you can disable copy constructors by overloading rvalue-references as well:
Example:
Say you have a base Binding<C> class, where C is either the base Constraint class, or an inherited class. Say you are storing Binding<C> by value in a vector, and you pass a reference to the binding and you wish to ensure that you do not cause an implicit copy.
You may do so by deleting func(Binding<C>&& x) (per PiotrNycz's example) for rvalue-reference specific cases.
Snippet:
template<typename T>
void overload_info(const T& x) {
cout << "overload: " << "const " << name_trait<T>::name() << "&" << endl;
}
template<typename T>
void overload_info(T&& x) {
cout << "overload: " << name_trait<T>::name() << "&&" << endl;
}
template<typename T>
void disable_implicit_copy(T&& x) = delete;
template<typename T>
void disable_implicit_copy(const T& x) {
cout << "[valid] ";
overload_info<T>(x);
}
...
int main() {
Constraint c;
LinearConstraint lc(1);
Binding<Constraint> bc(&c, {});
Binding<LinearConstraint> blc(&lc, {});
CALL(overload_info<Binding<Constraint>>(bc));
CALL(overload_info<Binding<LinearConstraint>>(blc));
CALL(overload_info<Binding<Constraint>>(blc));
CALL(disable_implicit_copy<Binding<Constraint>>(bc));
// // Causes desired error
// CALL(disable_implicit_copy<Binding<Constraint>>(blc));
}
Output:
>>> overload_info(bc)
overload: T&&
>>> overload_info<Binding<Constraint>>(bc)
overload: const Binding<Constraint>&
>>> overload_info<Binding<LinearConstraint>>(blc)
overload: const Binding<LinearConstraint>&
>>> overload_info<Binding<Constraint>>(blc)
implicit copy: Binding<LinearConstraint> -> Binding<Constraint>
overload: Binding<Constraint>&&
>>> disable_implicit_copy<Binding<Constraint>>(bc)
[valid] overload: const Binding<Constraint>&
Error (with clang-3.9 in bazel, when offending line is uncommented):
cpp_quick/prevent_implicit_conversion.cc:116:8: error: call to deleted function 'disable_implicit_copy'
CALL(disable_implicit_copy<Binding<Constraint>>(blc));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Full Source Code: prevent_implicit_conversion.cc
Well, I was going to answer this with the code below, but even though it works with Visual C++, in the sense of producing the desired compilation error, MinGW g++ 4.7.1 accepts it, and invokes the rvalue reference constructor!
I think it must be a compiler bug, but I could be wrong, so – anyone?
Anyway, here's the code, which may turn out to be a standard-compliant solution (or, it may turn out that that's a thinko on my part!):
#include <iostream>
#include <utility> // std::is_same, std::enable_if
using namespace std;
template< class Type >
struct Boxed
{
Type value;
template< class Arg >
Boxed(
Arg const& v,
typename enable_if< is_same< Type, Arg >::value, Arg >::type* = 0
)
: value( v )
{
wcout << "Generic!" << endl;
}
Boxed( Type&& v ): value( move( v ) )
{
wcout << "Rvalue!" << endl;
}
};
void function( Boxed< int > v ) {}
int main()
{
int i = 5;
function( i ); //<- this is acceptable
char c = 'a';
function( c ); //<- I would NOT like this to compile
}
I first tried PiotrNycz's approach (for C++03, which I'm forced to use for a project), then I tried to find a more general approach and came up with this ForcedType<T> template class.
template <typename T>
struct ForcedType {
ForcedType(T v): m_v(v) {}
operator T&() { return m_v; }
operator const T&() const { return m_v; }
private:
template <typename T2>
ForcedType(T2);
T m_v;
};
template <typename T>
struct ForcedType<const T&> {
ForcedType(const T& v): m_v(v) {}
operator const T&() const { return m_v; }
private:
template <typename T2>
ForcedType(const T2&);
const T& m_v;
};
template <typename T>
struct ForcedType<T&> {
ForcedType(T& v): m_v(v) {}
operator T&() { return m_v; }
operator const T&() const { return m_v; }
private:
template <typename T2>
ForcedType(T2&);
T& m_v;
};
If I'm not mistaken, those three specializations should cover all common use cases. I'm not sure if a specialization for rvalue-reference (on C++11 onwards) is actually needed or the by-value one suffices.
One would use it like this, in case of a function with 3 parameters whose 3rd parameter doesn't allow implicit conversions:
function(ParamType1 param1, ParamType2 param2, ForcedType<ParamType3> param3);