How to prioritize (tell compiler) to use "a function receive reference" (#B) over "a function receive value" (#A)?
#include <iostream>
using namespace std;
class Heavy{/* ...... */}; //a complex class
Heavy generateHeavy(){
return Heavy();
}
void f(Heavy x){ //#A I want LOW priority.
std::cout<<"case 1: pass by value"<<std::endl;
}
void f(Heavy& x){ //#B I want HIGH priority. (save CPU for big object)
std::cout<<"case 2: pass by reference"<<std::endl;
}
int main() {
//vvvv Here is existing code base that I don't want to touch.
f(generateHeavy()); //compiler call case 1 -> ok (I prefer reference, though)
Heavy heavy;
f(heavy); //should call case 2, but compiler fail (ambiguous) <= question
return 0;
}
This issue come from my first attempt to extend SFINAE to a real-world case that prefer passing by reference, if possible.
The way to literally do as you asked is
template <typename T = void>
std::enable_if_t<std::is_same<T, void>::value> f(Heavy x) { ... }
void f(Heavy& x) { ... }
The first is a function template, but only T = void is allowed. The second is not. All else being equal, non-templates are preferred over templates.
Now, in real code, you probably wouldn't do this. You'd look at which calls you wish to support, and find a more appropriate approach that fits those calls. #StoryTeller suggested &&:
void f(Heavy &&) { ... }
void f(Heavy &) { ... }
which means that when you've got an rvalue, such as your function result, the Heavy && overload will be called. That's usually fine, but note that it's not exactly the same as what you asked for:
const Heavy c;
f(c);
What you asked for would make this call f(Heavy). Instead, with the Heavy && overload, there is no overload that accepts this.
An additional overload void f(const Heavy &) could cover this. There's not enough information in the question to tell if this is an appropriate approach for your use case, but that's something that you should be able to figure out yourself.
Related
I was working on some generic code and thought it'd make a nice interface for a set of classes I plan to use in a variant if I could have a bunch of functions with the same name and parameters, but potentially different return types. For instance, maybe I'd like to have three classes that implement a function that might return int or std::vector<int> or void, where the returns represent some sequence of signals that propagate outwards in a system.
struct X{
//...
int update(double){
return 5;
}
};
struct Y{
//...
void update(double){
//Do something useful
}
};
struct Z{
//...
std::vector<int> update(double){
return {1,2,3,4};
}
};
Then, at some later point, I might have a generic function (e.g. acting as a visitor to a variant) like
template<class T>
void updateHandler(T& object){
auto ret = object.update(3.14);
if constexpr(std::is_same_v<decltype(ret), int>){
//Do something with an integer.
}else if constexpr(std::is_same_v<decltype(ret), std::vector<int> >){
//Do something with a vector of integers
}
}
But this won't work if updateHandler is called on an object of type Y because auto will deduce as void. While it's possible to test for the condition that the return type is void early via decltype, this would result in something like
template<class T>
void updateHandler(T& object){
if constexpr(std::is_void_v<decltype(object.update())>){
object.update();
}else{
auto ret = object.update();
if constexpr(std::is_same_v<decltype(ret), int>){
//Do something with an integer.
}else if constexpr(std::is_same_v<decltype(ret), std::vector<int> >){
//Do something with a vector of integers
}
}
}
where it's not as clear exactly what we're doing and somehow we've managed to duplicate our entire function call three times (!) in the code without being able to reduce this number in any obvious way.
I also had hoped that maybe there might be some funky rules to deal with this case, the same way that one can pass on a void return value in generic in the same way that
[](auto& object){ return object.update(3.14); }
is legal - I tried, for instance, using a template that might convert voids to values
template<class T>
decltype(auto) coverVoid(T&& input){
return input;
}
std::monostate coverVoid(void){
return {};
}
but this doesn't work since void isn't actually an argument (and I wouldn't really expect it to work, since void is, an incomplete type and you can't take a reference to it either). The best thing I could think of would be to hide all the repetition in a generic such as:
template<class Call, class Handle>
void handleMaybeVoid(Call&& call, Handle&& handle){
if constexpr(std::is_void_v<decltype(call())>){
call();
//Could then call handle(); if we wanted to handle void
}else{
handle(call());
}
}
and invoke that to implement updateHandler.
While I think there's an easy enough solution to this problem (just return an empty type instead of void in update - though this leads to a rather useless return {}; line), it surprises me that a void return seems to be so hard to handle in generic code. Is there a better way to deal with return values that are possibly void?
Consider the following bar functions
#include <iostream>
void foo(){
std::cout << "Hello" << std::endl;
}
void bar1(){
return foo();
}
void bar2(){
foo();
}
void bar3(){
foo();
return;
}
int main()
{
bar1();
bar2();
bar3();
return 1;
}
These functions do exactly the same thing, and actually godbolt produces the same code for all three (as one would hope). The question I have is simply whether there are any software engineering paradigms/guidelines that advocate one form over the other, and if there are any reasons why you would prefer one over the other. They seem to produce the same machine code, but I am imaging that one might be viewed as "easier to maintain", or something like that.
This is quite opinion-based. Though I'd say the general consensus is to write it like bar2(). Don't return explicitly unless you have to return early and don't do return func() if func() returns a void, that just confuses readers because you're not actually returning a value.
I totally agree with Sombrero Chicken's answer. But I'll also add that the construct like
void bar1(){
return foo();
}
doesn't make much sense for ordinary functions that return void, but may be useful for template code when you don't know the actual return type, e.g:
template <typename T>
auto SomeTemplateFunction(...)
{
// do some works
...
return SomeOtherTemplateFunction<T>(...);
}
This will work regardless SomeOtherTemplateFunction<T>'s return type is void or not.
It's quite opinion based, what I can say is that (3) is tagged by clang-tidy rules as part of the readibility-redundant-control-flow.
The idea is that the control flow here is already defined, the return is superfluous and should then be removed.
I have a simple class:
class A {
public:
bool f(int* status = nullptr) noexcept {
if (status) *status = 1;
return true;
}
void f() {
throw std::make_pair<int, bool>(1, true);
}
};
int main() {
A a;
a.f(); // <- Ambiguity is here! I want to call 'void f()'
}
I want to resolve ambiguity of a method call in favour of the exception-throwing method by any means.
The rationale behind such interface:
To have the noexcept(true) and noexcept(false) interface,
To allow optionally get extra information via a pointer in the noexcept(false) variant - while the noexcept(true) variant will always pack this information inside an exception.
Is it possible at all? Suggestions for a better interface are also welcome.
Having functions with this kind of signatures is obviously a bad design as you've found out. The real solutions are to have different names for them or to lose the default argument and were presented already in other answers.
However if you are stuck with an interface you can't change or just for the fun of it here is how you can explicitly call void f():
The trick is to use function pointer casting to resolve the ambiguity:
a.f(); // <- ambiguity is here! I want to call 'void f()'
(a.*(static_cast<void (A::*)()>(&A::f)))(); // yep... that's the syntax... yeah...
Ok, so it works, but don't ever write code like this!
There are ways to make it more readable.
Use a pointer:
// create a method pointer:
auto f_void = static_cast<void (A::*)()>(&A::f);
// the call is much much better, but still not as simple as `a.f()`
(a.*f_void)();
Create a lambda or a free function
auto f_void = [] (A& a)
{
auto f_void = static_cast<void (A::*)()>(&A::f);
(a.*f_void)();
};
// or
void f_void(A& a)
{
auto f_void = static_cast<void (A::*)()>(&A::f);
(a.*f_void)();
};
f_void(a);
I don't know if this is necessary better. The call syntax is definitely simpler, but it might be confusing as we are switching from a method call syntax to a free function call syntax.
Both versions f have different meanings.
They should have two different name, as:
f for the throwing one, because using it means that your are confident on success, and failure would be an exception in the program.
try_f() or tryF() for the error-return based one, because using it means that failure of the call is an expected outcome.
Two different meanings should be reflected in the design with two different name.
Because it seems fundamentally obvious to me, I may be missing something or may not fully understand your question. However, I think this does exactly what you want:
#include <utility>
class A {
public:
bool f(int* status) noexcept {
if (status) *status = 1;
return true;
}
void f() {
throw std::make_pair<int, bool>(1, true);
}
};
int main() {
A a;
a.f(); // <- now calls 'void f()'
a.f(nullptr); // calls 'bool f(int *)'
}
I simply removed the default argument from the noexcept variant. It's still possible to call the noexcept variant by passing nullptr as an argument, which seems a perfectly fine way of indicating that you want to call that particular variant of the function - after all, there's going to have to be some syntactic marker indicating which variant you want to call!
I agree with other users' suggestions to simply remove the default argument.
A strong argument in favour of such a design is that it would be in line with the new C++17 filesystem library, whose functions typically offer callers the choice between exceptions and error reference parameters.
See for example std::filesystem::file_size, which has two overloads, one of them being noexcept:
std::uintmax_t file_size( const std::filesystem::path& p );
std::uintmax_t file_size( const std::filesystem::path& p,
std::error_code& ec ) noexcept;
The idea behind this design (which is originally from Boost.Filesystem) is almost identical to yours, except of the default argument. Remove it and you do it like a brand new component of the standard library, which obviously can be expected not to have a completely broken design.
In C++14 it's ambiguous because noexcept is not part of the function signature. With that said...
You have a very strange interface. Although f(int* status = nullptr) is labelled noexcept, because it has a twin that does throw a exception, you are not really giving the caller a logical exception guarantee. It seems you simultaneously want f to always succeed while throwing an exception if the precondition is not met (status has a valid value, i.e not nullptr). But if f throws, what state is the object in? You see, your code is very hard to reason about.
I recommend you take a look at std::optional instead. It'll signal to the reader what you are actually trying to do.
C++ already has a type specifically used as an argument to disambiguate between throwing and non-throwing variants of a function: std::nothrow_t. You can use that.
#include <new>
class A {
public:
bool f(std::nothrow_t, int* status = nullptr) noexcept {
if (status) *status = 1;
return true;
}
void f() {
throw std::make_pair<int, bool>(1, true);
}
};
int main() {
A a;
a.f(); // Calls 'void f()'
a.f(std::nothrow); // Calls 'void f(std::nothrow_t, int*)'
}
Though I would still prefer an interface where the name distinguishes the variants, or possibly one where the distinction isn't necessary.
Here's a purely compile-time method.
It may be useful if your compiler happens to have trouble optimizing away function pointer calls.
#include <utility>
class A {
public:
bool f(int* status = nullptr) noexcept {
if (status) *status = 1;
return true;
}
void f() {
throw std::make_pair<int, bool>(1, true);
}
};
template<void (A::*F)()>
struct NullaryFunction {
static void invoke(A &obj) {
return (obj.*F)();
}
};
int main() {
A a;
// a.f(); // <- Ambiguity is here! I want to call 'void f()'
NullaryFunction<&A::f>::invoke(a);
}
So you are trying to throw an exception if the code is unprepared for an error return?
Then, how about
class ret
{
bool success;
mutable bool checked;
int code;
public:
ret(bool success, int code) : success(success), checked(false), code(code) { }
~ret() { if(!checked) if(!success) throw code; }
operator void *() const { checked = true; return reinterpret_cast<void *>(success); }
bool operator!() const { checked = true; return !success; }
int code() const { return code; }
};
This is still an Abomination unto Nuggan though.
By removing the if(!success) check in the destructor, you can make the code throw whenever a return code is not looked at.
I am trying to write some templated functions that accept either a std::basic_string or a char array from which the basic_string could be constructed.
My current solution is:
#include <string>
template<typename CharT>
void foo(std::basic_string<CharT> str)
{
(void)str; // do something with str
}
template<typename CharT>
void foo(CharT const * arr)
{
return foo(std::basic_string<CharT>{arr});
}
int main(void)
{
foo("hello");
foo(std::string{ "hello" });
foo(L"hello");
foo(std::wstring{ L"hello" });
}
But this means that for each function I have to write another function that calls the first one. That's pretty annoying; is there an easier way to do it? Maybe it could be a template deduction guide, but as far as I know it does not exist for functions, only classes.
The first templated function is not sufficient because the template deduction fails: the compiler cannot deduce CharT in std::basic_string<CharT> from CharT const *. That is why I need a simpler way to tell this to the compiler.
Just bite the bullet and use 2 overloads. Any clever solution (which as davidhigh showed do exist) will only add unnecessary complexity, potential for bugs and confusion to the next reader.
You only write once but read multiple times. The small incovenient of writing a 1 line of body overload is worth doing against an non-idiomatic convoluted smart way.
Don't get me wrong, I love to find these smart solutions in C++, but if I found this solution in a production code it would take me a few good minutes just to figure out what the heck it is and what does it do, only to find out it just does what should have been a very basic thing in a complex way, I would ... well let's just say I wouldn't say nice things about the author of the code. Being lazy when writing code will cost you times over when you maintain, debug, extend, or even use the code.
Write simple, idiomatic and easy to understand code!
After a bit more of research, the best option imo is to use the C++17 feature std::basic_string_view:
template<typename CharT>
void foo(std::basic_string_view<CharT> str)
{
(void)str; // do something with str ...
// while remembering that string_view does not own the string
}
So forget about the older explanation below if you have access to a C++17-compiler.
There are two cases here to consider. The first case is that you do not really want to do something special with the basic string, but rather you apply only methods also available for the char-array (and just want to make sure it's called correctly regardless of the parameters). In this case, I'd simply use a general template parameter:
template<typename string_type
/* possibly some SFINAE to allow/disallow certain types */>
auto foo(string_type s)
{
std::cout << s << std::endl;
}
Second case is that you really want to do some special operation on the string which is not present for the char array. In this case you need an overload for basic_string, but you probably want to write it only once and not for each and every function you use. This is what the following string_invoker class tries to do (but it still needs some improvement, just working on it):
template<typename method>
struct string_invoker_impl
{
string_invoker_impl(method m) : m(m) {}
template<typename CharT>
auto operator()(std::basic_string<CharT> str) const
{
return m(str);
}
template<typename CharT>
auto operator()(CharT const * arr) const
{
return operator()(std::basic_string<CharT>{arr});
}
//possibly further methods for non-const array's, modification, etc.
method m;
};
auto string_invoker = [](auto m) { return string_invoker_impl<decltype(m)>{m}; };
auto foo_impl = [](auto str) {std::cout<< str <<std::endl; };
auto foo = string_invoker(foo_impl);
//you can merge the previous two calls also in a single one:
//auto foo = string_invoker( [](auto str) {std::cout<< str <<std::endl; });
int main(void)
{
foo("hello");
foo(std::string{ "hello" });
//foo(L"hello"); //need std::wcout, thus it fails with std::cout
//but it's no general problem, just overload your foo_impl function
//foo(std::wstring{ L"hello" });
}
DEMO
I am creating a mechanism which allows users to form arbitrary complex functions from basic building blocks using the decorator pattern. This works fine functionality wise, but I don't like the fact that it involves a lot of virtual calls, particularly when the nesting depth becomes large. It worries me because the complex function may called often (>100.000 times).
To avoid this problem, I tried to turn the decorator scheme into a std::function once it was finished (cfr. to_function() in the SSCCE). All internal function calls are wired during construction of the std::function. I figured this would be faster to evaluate than the original decorator scheme because no virtual lookups need to be performed in the std::function version.
Alas, benchmarks prove me wrong: the decorator scheme is in fact faster than the std::function I built from it. So now I am left wondering why. Maybe my test setup is faulty since I only use two trivial basic functions, which means the vtable lookups may be cached?
The code I used is included below, unfortunately it is quite long.
SSCCE
// sscce.cpp
#include <iostream>
#include <vector>
#include <memory>
#include <functional>
#include <random>
/**
* Base class for Pipeline scheme (implemented via decorators)
*/
class Pipeline {
protected:
std::unique_ptr<Pipeline> wrappee;
Pipeline(std::unique_ptr<Pipeline> wrap)
:wrappee(std::move(wrap)){}
Pipeline():wrappee(nullptr){}
public:
typedef std::function<double(double)> FnSig;
double operator()(double input) const{
if(wrappee.get()) input=wrappee->operator()(input);
return process(input);
}
virtual double process(double input) const=0;
virtual ~Pipeline(){}
// Returns a std::function which contains the entire Pipeline stack.
virtual FnSig to_function() const=0;
};
/**
* CRTP for to_function().
*/
template <class Derived>
class Pipeline_CRTP : public Pipeline{
protected:
Pipeline_CRTP(const Pipeline_CRTP<Derived> &o):Pipeline(o){}
Pipeline_CRTP(std::unique_ptr<Pipeline> wrappee)
:Pipeline(std::move(wrappee)){}
Pipeline_CRTP():Pipeline(){};
public:
typedef typename Pipeline::FnSig FnSig;
FnSig to_function() const override{
if(Pipeline::wrappee.get()!=nullptr){
FnSig wrapfun = Pipeline::wrappee->to_function();
FnSig processfun = std::bind(&Derived::process,
static_cast<const Derived*>(this),
std::placeholders::_1);
FnSig fun = [=](double input){
return processfun(wrapfun(input));
};
return std::move(fun);
}else{
FnSig processfun = std::bind(&Derived::process,
static_cast<const Derived*>(this),
std::placeholders::_1);
FnSig fun = [=](double input){
return processfun(input);
};
return std::move(fun);
}
}
virtual ~Pipeline_CRTP(){}
};
/**
* First concrete derived class: simple scaling.
*/
class Scale: public Pipeline_CRTP<Scale>{
private:
double scale_;
public:
Scale(std::unique_ptr<Pipeline> wrap, double scale) // todo move
:Pipeline_CRTP<Scale>(std::move(wrap)),scale_(scale){}
Scale(double scale):Pipeline_CRTP<Scale>(),scale_(scale){}
double process(double input) const override{
return input*scale_;
}
};
/**
* Second concrete derived class: offset.
*/
class Offset: public Pipeline_CRTP<Offset>{
private:
double offset_;
public:
Offset(std::unique_ptr<Pipeline> wrap, double offset) // todo move
:Pipeline_CRTP<Offset>(std::move(wrap)),offset_(offset){}
Offset(double offset):Pipeline_CRTP<Offset>(),offset_(offset){}
double process(double input) const override{
return input+offset_;
}
};
int main(){
// used to make a random function / arguments
// to prevent gcc from being overly clever
std::default_random_engine generator;
auto randint = std::bind(std::uniform_int_distribution<int>(0,1),std::ref(generator));
auto randdouble = std::bind(std::normal_distribution<double>(0.0,1.0),std::ref(generator));
// make a complex Pipeline
std::unique_ptr<Pipeline> pipe(new Scale(randdouble()));
for(unsigned i=0;i<100;++i){
if(randint()) pipe=std::move(std::unique_ptr<Pipeline>(new Scale(std::move(pipe),randdouble())));
else pipe=std::move(std::unique_ptr<Pipeline>(new Offset(std::move(pipe),randdouble())));
}
// make a std::function from pipe
Pipeline::FnSig fun(pipe->to_function());
double bla=0.0;
for(unsigned i=0; i<100000; ++i){
#ifdef USE_FUNCTION
// takes 110 ms on average
bla+=fun(bla);
#else
// takes 60 ms on average
bla+=pipe->operator()(bla);
#endif
}
std::cout << bla << std::endl;
}
Benchmark
Using pipe:
g++ -std=gnu++11 sscce.cpp -march=native -O3
sudo nice -3 /usr/bin/time ./a.out
-> 60 ms
Using fun:
g++ -DUSE_FUNCTION -std=gnu++11 sscce.cpp -march=native -O3
sudo nice -3 /usr/bin/time ./a.out
-> 110 ms
You have std::functions binding lambdas that call std::functions that bind lamdbas that call std::functions that ...
Look at your to_function. It creates a lambda that calls two std::functions, and returns that lambda bound into another std::function. The compiler won't resolve any of these statically.
So in the end, you end with with just as many indirect calls as the virtual function solution, and that's if you get rid of the bound processfun and directly call it in the lambda. Otherwise you have twice as many.
If you want a speedup, you will have to create the entire pipeline in a way that can be statically resolved, and that means a lot more templates before you can finally erase the type into a single std::function.
As Sebastian Redl's answer says, your "alternative" to virtual functions adds several layers of indirection through dynamically bound functions (either virtual, or through function pointers, depending on the std::function implementation) and then it still calls the virtual Pipeline::process(double) function anyway!
This modification makes it significantly faster, by removing one layer of std::function indirection and preventing the call to Derived::process being virtual:
FnSig to_function() const override {
FnSig fun;
auto derived_this = static_cast<const Derived*>(this);
if (Pipeline::wrappee) {
FnSig wrapfun = Pipeline::wrappee->to_function();
fun = [=](double input){
return derived_this->Derived::process(wrapfun(input));
};
} else {
fun = [=](double input){
return derived_this->Derived::process(input);
};
}
return fun;
}
There's still more work being done here than in the virtual function version though.
std::function is notoriously slow; type erasure and the resulting allocation play a part in this, also, with gcc, invocations are inlined/optimized badly. For this reason there exist a plethora of C++ "delegates" with which people attempt to resolve this problem. I ported one to Code Review:
https://codereview.stackexchange.com/questions/14730/impossibly-fast-delegate-in-c11
But you can find plenty of others with Google, or write your own.
EDIT:
These days, look here for a fast delegate.
libstdc++ implementation of std::function works roughly as follows:
template<typename Signature>
struct Function
{
Ptr functor;
Ptr functor_manager;
template<class Functor>
Function(const Functor& f)
{
functor_manager = &FunctorManager<Functor>::manage;
functor = new Functor(f);
}
Function(const Function& that)
{
functor = functor_manager(CLONE, that->functor);
}
R operator()(args) // Signature
{
return functor_manager(INVOKE, functor, args);
}
~Function()
{
functor_manager(DESTROY, functor);
}
}
template<class Functor>
struct FunctorManager
{
static manage(int operation, Functor& f)
{
switch (operation)
{
case CLONE: call Functor copy constructor;
case INVOKE: call Functor::operator();
case DESTROY: call Functor destructor;
}
}
}
So although std::function doesn't know the exact type of the Functor object, it dispatches the important operations through a functor_manager function pointer that is a static function of a template instance that does know about the Functor type.
Each std::function instance will allocate on the heap its own owned copy of the functor object (unless it is not larger than a pointer, such as a function pointer, in which case it just holds the pointer as a subobject).
The important take away is that copying of std::function is expensive if the underlying functor object has an expensive copy constructor and/or takes lots of space (for example to hold bound parameters).