The using declaration and function default arguments - c++

According to the C++ 17 Standard (10.3.3 The using declaration)
1 Each using-declarator in a using-declaration98 introduces a set of
declarations into the declarative region in which the
using-declaration appears.
and
10 A using-declaration is a declaration and can therefore be used
repeatedly where (and only where) multiple declarations are allowed.
and (The C++ 17 Standard, 11.3.6 Default arguments)
...When a declaration of a function is introduced by way of a
using-declaration (10.3.3), any default argument information
associated with the declaration is made known as well. If the function
is redeclared thereafter in the namespace with additional default
arguments, the additional arguments are also known at any point
following the redeclaration where the using-declaration is in scope.
So this program
#include <iostream>
void f( int x, int y = 20 )
{
std::cout << "x = " << x << ", y = " << y << '\n';
}
int main()
{
using ::f;
void f( int, int );
f( 10 );
return 0;
}
as expected compiles and outputs
x = 10, y = 20
In fact it is similar to the program
#include <iostream>
void f( int x, int y )
{
std::cout << "x = " << x << ", y = " << y << '\n';
}
int main()
{
void f( int, int = 20 );
void f( int, int );
f( 10 );
return 0;
}
Now it would be logical consistent that the following program also was valid.
#include <iostream>
void f( int x, int y = 20 )
{
std::cout << "x = " << x << ", y = " << y << '\n';
}
int main()
{
using ::f;
void f( int, int );
f( 10 );
void f( int = 10, int );
f();
return 0;
}
However this program does not compile.
On the other hand, consider the following program.
#include <iostream>
namespace N
{
int a = 10;
int b = 20;
void f( int, int = b );
}
int a = 30;
int b = 40;
void N::f( int x = a, int y )
{
std::cout << "x = " << x << ", y = " << y << '\n';
}
int main()
{
using N::f;
f();
return 0;
}
It compiles successfully and its output is
x = 10, y = 20
So could be the same principles applied to functions introduced by the using declaration?
What is the reason of that such an addition of default arguments is not allowed?

You can only declare new default arguments in the same scope as the original declaration. using does not change this.
For non-template functions, default arguments can be added in later declarations of a function in the same scope.
dcl.fct.default/4

I believe
any default argument information associated with the declaration is made known as well
doesn't mean the arguments are actually imported into the scope, it's just known that they do exist and can be used.
That would mean that void f( int = 10, int ); isn't adding to void f( int x, int y = 20 ), but is instead trying to add to void f( int, int ); which would be illegal as there isn't a default argument for the second parameter in the scope that the using declaration is in.

Related

How can std::reference_wrapper<int> use operator+= if std::reference_wrapper doesn't have operator+=?

Thank you all, I didn't even know about user-defined conversion function and how it works.
Why is it possible to use std::reference_wrapper<int>::operator+=, if such an operator does not exist, are there some implicit conversions?
#include <iostream>
#include <functional>
#include <boost/type_index.hpp>
using boost::typeindex::type_id_with_cvr;
template <typename C>
void test(C c)
{
c += 1;
}
int main()
{
int a = 3;
test(a);
std::cout << a << std::endl;
test(std::ref(a));
std::cout << a << std::endl;
}
Output:
3
4
To check that template works perfectly fine:
void test_2(std::reference_wrapper<int> c)
{
c += 1;
}
int main()
{
int a = 3;
test_2(std::ref(a));
std::cout << a << std::endl;
}
Output:
4
Still works as before. How is that possible?
Funny thing, that in auto d = b + c, d has an integer type.
int main()
{
auto b = std::ref(a);
auto c = std::ref(a);
auto d = b + c;
std::cout << type_id_with_cvr<decltype(d)>).pretty_name() << std::endl;
}
Output:
int
It's because it's implicitly convertible to a reference to T:
/* constexpr [c++20] */ operator T& () const noexcept;
In your case, it's implicitly convertible to an int&.
This ability to be implicitly convertible to an int& is also what would make it possible for you to define your function to take an int& while passing it a std::reference_wrapper<int>:
void test_2(int& c) // <--+
{ // |
c += 1; // |
} // |
int main() { // |
// ... // |
test_2(std::ref(a)); // >--+
}

Should we capture by const reference in lambda?

I have been reading Lambda capture as const reference?
It is an interesting feature, and sometimes I also wish this feature to exist, especially when I have huge data, which I need to access inside a lambda function.
My follow up questions -
Should we capture by const reference in lambda? If yes, how should it be behave?
(Edit - I am also interested in the behaviour of the lifetime of the captured variable.)
Is there any possible downside, by introducing it in the C++ grammar? (I can't think of any)
Let us assume we can.
We assume [const &] as syntax to capture.
int x = 10;
auto lambda = [const & x](){ std::cout << x << std::endl; };
lambda(); // prints 10, great, as expected
x = 11;
lambda(); // should it print 11 or 10 ?
My intuition is that is should behave just like [&] but the captured value should not be allowed to modify.
template<typename Func>
void higher_order_function(int & x, Func f)
{
f(); // should print 11
x = 12;
f(); // should print 12
}
void foo()
{
int x = 10;
auto c = [const & x] () { std::cout << x << std::endl; };
c(); // should print 10
x = 11;
c(); // should print 11
higher_order_function(x, c);
auto d = [const & x] () { x = 13; }; // Compiler ERROR: Tried to assign to const qualified type 'const int &'!
}
I've been wondering about this myself.
Since the operator() is const by default, I would assume that allowing const references is acceptable as well.
With the current standards(C++17), the closest I got to this behaviour is:
auto c = [ &x = std::as_const(x) ] () { std::cout << x << std::endl; };
Workaround in C++11/C++14 would be(thanks to Daniel for suggestion):
auto const & crx = x;
auto c = [ &crx ] () { std::cout << crx << std::endl; };
lambda(); // should it print 11 or 10 ?
I don't understand why it should print 10. Consider lambda being just an instance of some anonymous class. Making it a normal class, it should look like:
class Lambda {
public:
Lambda(const int & i) : i_(i) { }
void operator()() { std::cout << i_ << std::endl; }
private:
const int & i_;
};
int x = 10;
Lambda lambda(x);
lambda(); // prints 10, great, as expected
x = 11;
lambda(); // should it print 11 or 10 ?
The meaning of const reference here is only that you cannot modify x through i_ member reference variable.
A simlpler scenario:
int x = 10;
const int & crx = x;
x++;
std::cout << crx << std::endl; // prints 11
Maybe not exactly what you're looking for but... I suppose you can pass through a function that receive the same value by const reference.
Something as follows
template <typename T>
auto make_capture_const (T const & x)
{ return [&x](){ std::cout << x << std::endl; }; }
// ...
int x { 42 };
auto l = make_capture_const(x);
l();
If you try to modify x inside the lambda
std::cout << x++ << std::endl;
you should get an error.
As you can see, from, this solution you get that x can't be modified inside the lambda but the lambda is influenced from the value changes outside
int x { 42 };
auto l = make_capture_const(x);
l(); // print 42
x = 43;
l(); // print 43
IMHO, an hypothetic [const &] capture syntax should works in the same way. But I understand that is highly questionable.

Is there a macro-based adapter to make a functor from a class?

Creating a functor requires an unnecessary boiler plate. The state has to be written 4 times!
struct f{
double s; // 1st
f(double state): s(state) {} // 2nd, 3rd and 4th
double operator() (double x) {
return x*s;
}
};
is there a library with a macro that would be just double functor(state)(x){ return x*state; } or something similar.
BOOST_FOREACH is a macro adapter that works well. I'm looking for something similar.
any suggestions on how to write one is appreciated too.
ps. using struct for functor is faster then bind Class's operator() or bind a function as a functor?
Update(1)
in regards to lambdas:
the functor has to be modular, meaning, it should be reusable in other function. lambdas have to be within a function -- lambda has to be in main to be called from main and other functions outside of main, can't call the lambda defined in main.
How about relying on aggregate initialization? Simply do not declare the constructor:
struct f {
double s;
double operator()(double x) {
return x * s;
}
};
use it like this
int main()
{
auto ff = f{42};
std::cout << ff(2);
return 0;
}
Define the functionality you want, e.g., you multiplication, as a function and then use std::bind() to create a suitable function object:
#include <functional>
double some_operation(double state, double x) {
return state * x;
}
int main() {
auto function = std::bind(&some_operation, 17, std::placeholders::_1);
return function(18);
}
Since a call through a function pointer generally can't be inlined, you might want to write your function as a function object instead:
#include <functional>
struct some_operation {
double operator()(double state, double x) const {
return state * x;
}
};
int main() {
auto function = std::bind(some_operation(), 17, std::placeholders::_1);
return function(18);
}
Below is a test program which seems to indicate that the speed of a hand-crafted function object and a bound function object are about the same, i.e., the results I get are
in 90 ms, functor as a struct; result = 1.5708e+16
in 262 ms, function pointer through bind; result = 1.5708e+16
in 261 ms, function through bind; result = 1.5708e+16
in 87 ms, function object through bind; result = 1.5708e+16
in 88 ms, non-called bind with function; result = 1.5708e+16
in 88 ms, non-called bind with function pointer; result = 1.5708e+16
using a recent version of clang (more precisely: clang version 3.4 (trunk 182411)) on a MacOS system optimizing with -O2 option. Using and gcc (more precisely: gcc version 4.9.0 20130811 (experimental) (GCC)) gives similar results.
It seems it makes a difference whether the function object is build in the local context or passed via template argument to a separate function. This difference is interesting as I would expect that most of the uses of bind() a function will result in passing off the resulting function object somewhere.
The code is based on https://stackoverflow.com/a/18175033/1120273:
#include <iostream>
#include <functional>
#include <chrono>
using namespace std;
using namespace std::placeholders;
using namespace std::chrono;
struct fs {
double s;
fs(double state) : s(state) {}
double operator()(double x) {
return x*s;
}
};
struct ff {
double operator()(double x, double state) const {
return x * state;
}
};
double fb(double x, double state) {
return x*state;
}
template <typename Function>
void measure(char const* what, Function function)
{
const auto stp1 = high_resolution_clock::now();
double sresult(0.0);
for(double x=0.0; x< 1.0e8; ++x) {
sresult += function(x);
}
const auto stp2 = high_resolution_clock::now();
const auto sd = duration_cast<milliseconds>(stp2 - stp1);
cout << "in " << sd.count() << " ms, ";
cout << what << "; result = " << sresult << endl;
}
int main() {
double state=3.1415926;
measure("functor as a struct", fs(state));
measure("function through bind", std::bind(&fb, _1, state));
measure("function object through bind", std::bind(ff(), _1, state));
{
const auto stp1 = high_resolution_clock::now();
double sresult(0.0);
auto function = std::bind(fb, _1, state);
for(double x=0.0; x< 1.0e8; ++x) {
sresult += function(x);
}
const auto stp2 = high_resolution_clock::now();
const auto sd = duration_cast<milliseconds>(stp2 - stp1);
cout << "in " << sd.count() << " ms, ";
cout << "embedded bind with function; result = " << sresult << endl;
}
{
const auto stp1 = high_resolution_clock::now();
double sresult(0.0);
auto function = std::bind(&fb, _1, state);
for(double x=0.0; x< 1.0e8; ++x) {
sresult += function(x);
}
const auto stp2 = high_resolution_clock::now();
const auto sd = duration_cast<milliseconds>(stp2 - stp1);
cout << "in " << sd.count() << " ms, ";
cout << "embedded bind with function pointer; result = " << sresult << endl;
}
return 0;
}
We've got lambdas for this:
double s = 42;
auto f = [s](double x) {
return s * x;
};
Down to single mention of state on line 2 (as you dont seem to count one in the actual expression). Whether initialization on line 1 counts as mention is debatable, your desired form does not contain any initialization, which is required, so I assume this to be acceptable.
In c++14 we'll get extension of lambda capture syntax allowing even more terse form:
auto f = [s{42}](double x) {
return s * x;
};
Have a look at BOOST_LOCAL_FUNCTION which seems to be exactly what youre looking for, as you even mention a macro :)
double s = 42;
double BOOST_LOCAL_FUNCTION(bind& s, double x) {
return x*s;
} BOOST_LOCAL_FUNCTION_NAME(f)
Personal note: If you have a modern compiler, go with C++11 lambdas.

C++ and currying

I've the code:
#include <iostream>
using namespace std;
auto fn = ([](int x){
return [x](int y) {
return x * y;
};
});
int main() {
int i = fn(2)(4); // 8
cout << i << endl;
return 0;
}
This code works fine.
However, I want to call a second function later like:
auto i = fn(2);
i(4); //error: 'i' cannot be used as a function
Are there any way to call the last function later and then bind with the first call?
The following works as expected
#include <iostream>
using namespace std;
auto fn = [](int x){
return [x](int y) {
return x * y;
};
};
int main() {
auto i = fn(2)(4); // 8
cout << i << endl;
auto j = fn(2);
cout << j(4) << endl;
return 0;
}
ADD
By the way gcc 4.5 with -std=c++0x gives the following error if you use int instead of auto:
currying.cpp:17:17: error: cannot convert ‘<lambda(int)>::<lambda(int)>’ to ‘int’ in initialization
currying.cpp:19:16: error: ‘j’ cannot be used as a function
which is an "obvious" and useful information to get what's going wrong.
The result of fn is not an integer, so you cannot assign fn(2) to an integer (don't even know why that compiles).
You should be able to do auto i = fn(2);
This works for me:
int main() {
auto i = fn(2);
cout << i(4) << endl; // prints 8
return 0;
}

How to pass optional arguments to a method in C++?

How to pass optional arguments to a method in C++ ?
Any code snippet...
Here is an example of passing mode as optional parameter
void myfunc(int blah, int mode = 0)
{
if (mode == 0)
do_something();
else
do_something_else();
}
you can call myfunc in both ways and both are valid
myfunc(10); // Mode will be set to default 0
myfunc(10, 1); // Mode will be set to 1
An important rule with respect to default parameter usage:
Default parameters should be specified at right most end, once you specify a default value parameter you cannot specify non default parameter again.
ex:
int DoSomething(int x, int y = 10, int z) -----------> Not Allowed
int DoSomething(int x, int z, int y = 10) -----------> Allowed
It might be interesting to some of you that in case of multiple default parameters:
void printValues(int x=10, int y=20, int z=30)
{
std::cout << "Values: " << x << " " << y << " " << z << '\n';
}
Given the following function calls:
printValues(1, 2, 3);
printValues(1, 2);
printValues(1);
printValues();
The following output is produced:
Values: 1 2 3
Values: 1 2 30
Values: 1 20 30
Values: 10 20 30
Reference: http://www.learncpp.com/cpp-tutorial/77-default-parameters/
To follow the example given here, but to clarify syntax with the use of header files, the function forward declaration contains the optional parameter default value.
myfile.h
void myfunc(int blah, int mode = 0);
myfile.cpp
void myfunc(int blah, int mode) /* mode = 0 */
{
if (mode == 0)
do_something();
else
do_something_else();
}
With the introduction of std::optional in C++17 you can pass optional arguments:
#include <iostream>
#include <string>
#include <optional>
void myfunc(const std::string& id, const std::optional<std::string>& param = std::nullopt)
{
std::cout << "id=" << id << ", param=";
if (param)
std::cout << *param << std::endl;
else
std::cout << "<parameter not set>" << std::endl;
}
int main()
{
myfunc("first");
myfunc("second" , "something");
}
Output:
id=first param=<parameter not set>
id=second param=something
See https://en.cppreference.com/w/cpp/utility/optional
Use default parameters
template <typename T>
void func(T a, T b = T()) {
std::cout << a << b;
}
int main()
{
func(1,4); // a = 1, b = 4
func(1); // a = 1, b = 0
std::string x = "Hello";
std::string y = "World";
func(x,y); // a = "Hello", b ="World"
func(x); // a = "Hello", b = ""
}
Note : The following are ill-formed
template <typename T>
void func(T a = T(), T b )
template <typename T>
void func(T a, T b = a )
With commas separating them, just like parameters without default values.
int func( int x = 0, int y = 0 );
func(); // doesn't pass optional parameters, defaults are used, x = 0 and y = 0
func(1, 2); // provides optional parameters, x = 1 and y = 2
Typically by setting a default value for a parameter:
int func(int a, int b = -1) {
std::cout << "a = " << a;
if (b != -1)
std::cout << ", b = " << b;
std::cout << "\n";
}
int main() {
func(1, 2); // prints "a=1, b=2\n"
func(3); // prints "a=3\n"
return 0;
}
Jus adding to accepted ans of #Pramendra , If you have declaration and definition of function, only in declaration the default param need to be specified