I created two files, Linkage.cpp and External.cpp.
Linkage.cpp:
#include <iostream>
void Log(int x = 5)
{
std::cout << x << "\n";
}
int main()
{
Log();
return 0;
}
External.cpp:
#include <iostream>
void Log(const char* message)
{
std::cout << message << "\n";
}
Why am I not getting a linker error? Both these functions are defined in the global namespace, so there should be naming conflicts as with variables.
Why am I not getting a linker error?
When you wrote
void Log(int x = 5)//this means that the function named Log can be called without passing
//any argument because you have provided a default argument which will be
//used in case you don't provide/pass any argument
{
//..other code here
{
The above means that the function named Log can be called without passing any argument because you have provided a default argument which will be used in case you don't provide/pass any argument.
Next when you wrote
void Log(const char* message)//this means that this versoin of the function named Log will be called only if you pass an argument of type `char*` .
{
std::cout << message << "\n";
}
The above means that this verion of the function named Log will be called only if you pass an argument of type char* .
Now when your wrote:
Log();
The first version which has a default argument will be used because you haven't provided any argument and so the first version can be used(since it is viable) and because the second version which must take an argument is not viable.
Okay, I experimented around after #Retire Ninja pointed this out to me.
First, comment out all the code from External.cpp. Now, declare another Log function inside Linkage.cpp so that there are two functions inside this file that have the same name(Log) but different parameters. You will realise that using depending upon what arguments you supply, these Log functions will behave like different functions.
So, unlike variables, where same name means same variable in a namespace, functions need to have matching signatures too.
Related
I'm trying to find a way to provide pointers to a member functions between different class instances. For the moment I'm able to provide pointers to member function that takes no arguments but cannot manage to do so when the function to point to has an argument.
A sample code to illustrate my problem :
#include <iostream>
class Event
{
public:
std::string type;
Event(std::string type):type(type){}
};
class EventDispatcherBase
{
public:
void addEventListener(std::function<void(Event &event)> listener)
{
Event myEvent("Type of the myEvent object");
listener(myEvent);
}
};
class EventDispatcherClass:public EventDispatcherBase
{
public:
EventDispatcherClass()
{
addEventListener([](Event &event){std::cout << event.type << std::endl;});
//addEventListener([this]{listener(Event event);});
};
void listener(Event &event)
{
std::cout << event.type << std::endl;
}
};
int main()
{
EventDispatcherClass eventDispatcherClass;
return 0;
}
This code works with an anonymous lambda expression and output "Type of the myEvent object" in the console. But if I uncomment the line
addEventListener([this]{listener(Event event);});
in the constructor of the EventDispatcherClass in order to transmit a pointer to the void listener(Event &event) member function, the compiler throw the following error :
no viable conversion from '(lambda at .../main.cpp:27:26)' to
'std::function'
I don't understand why.
but cannot manage to do so when the function to point to has an argument.
The lambda should take an argument of type Event&, which will be forwarded to the member function inside the lambda. So change it to
addEventListener([this](Event &event){listener(event);});
// ^^^^^^^^^^^^^^
LIVE
The working line:
addEventListener([](Event &event){std::cout << event.type << std::endl;});
looks nothing like the broken one:
//addEventListener([this]{listener(Event event);});
so start by changing the working line bit by bit.
add the capture expression you will want, and it still works
addEventListener([this](Event &event){std::cout << event.type << std::endl;});
change the body to the one you want, and it still works
addEventListener([this](Event &event){ this->listener(event); });
If you're having trouble seeing what's different between the two versions - which is actually pretty common when you wrote them yourself and you're seeing what you intended to type instead of what's there - try changing the layout to line everything up (so you'd see the missing (Event &event)), or transforming one into the other step-by-step as above, or just replace one with the other and diff the file versions.
just change it to addEventListener(listener);
and make the function itself static as static void listener(Event &event)
std::experimental::source_location will probably be added to the C++ standard at some point. I'm wondering if it possible to get the location information into the compile-time realm. Essentially, I want a function that returns different types when called from different source locations. Something like this, although it doesn't compile because the location object isn't constexpr as it's a function argument:
#include <experimental/source_location>
using namespace std::experimental;
constexpr auto line (const source_location& location = source_location::current())
{
return std::integral_constant<int, location.line()>{};
}
int main()
{
constexpr auto ll = line();
std::cout << ll.value << '\n';
}
This doesn't compile, with a message about
expansion of [...] is not a constant expression
regarding the return std::integral_constant<int, location.line()>{} line. What good it is to have the methods of source_location be constexpr if I can't use them?
As Justin pointed the issue with your code is that function argument are not constexpr but the problem of using source_location in a constexpr function in a more useful way is mentioned in the constexpr! functions proposal which says:
The "Library Fundamentals v. 2" TS contains a "magic" source_location
class get to information similar to the FILE and LINE macros
and the func variable (see N4529 for the current draft, and N4129
for some design notes). Unfortunately, because the "value" of a
source_location is frozen at the point source_location::current() is
invoked, composing code making use of this magic class is tricky:
Typically, a function wanting to track its point of invocation has to
add a defaulted parameter as follows:
void my_log_function(char const *msg,
source_location src_loc
= source_location::current()) {
// ...
}
This idiom ensure that the value of the source_location::current()
invocation is sampled where my_log_function is called instead of where
it is defined.
Immediate (i.e., constexpr!) functions, however, create a clean
separation between the compilation process and the constexpr
evaluation process (see also P0992). Thus, we can make
source_location::current() an immediate function, and wrap it as
needed in other immediate functions: The value produced will
correspond to the source location of the "root" immediate function
call. For example:
constexpr! src_line() {
return source_location::current().line();
}
void some_code() {
std::cout << src_line() << '\n'; // This line number is output.
}
So this is currently an open problem.
This question already has answers here:
Default value of function parameter
(5 answers)
Closed 5 years ago.
What's the place for the default parameter value? Just in function definition, or declaration, or both places?
Default parameter values must appear on the declaration, since that is the only thing that the caller sees.
EDIT: As others point out, you can have the argument on the definition, but I would advise writing all code as if that wasn't true.
You can do either, but never both. Usually you do it at function declaration and then all callers can use that default value. However you can do that at function definition instead and then only those who see the definition will be able to use the default value.
C++ places the default parameter logic in the calling side, this means that if the default value expression cannot be computed from the calling place, then the default value cannot be used.
Other compilation units normally just include the declaration so default value expressions placed in the definition can be used only in the defining compilation unit itself (and after the definition, i.e. after the compiler sees the default value expressions).
The most useful place is in the declaration (.h) so that all users will see it.
Some people like to add the default value expressions in the implementation too (as a comment):
void foo(int x = 42,
int y = 21);
void foo(int x /* = 42 */,
int y /* = 21 */)
{
...
}
However, this means duplication and will add the possibility of having the comment out of sync with the code (what's worse than uncommented code? code with misleading comments!).
Although this is an "old" thread, I still would like to add the following to it:
I've experienced the next case:
In the header file of a class, I had
int SetI2cSlaveAddress( UCHAR addr, bool force );
In the source file of that class, I had
int CI2cHal::SetI2cSlaveAddress( UCHAR addr, bool force = false )
{
...
}
As one can see, I had put the default value of the parameter "force" in the class source file, not in the class header file.
Then I used that function in a derived class as follows (derived class inherited the base class in a public way):
SetI2cSlaveAddress( addr );
assuming it would take the "force" parameter as "false" 'for granted'.
However, the compiler (put in c++11 mode) complained and gave me the following compiler error:
/home/.../mystuff/domoproject/lib/i2cdevs/max6956io.cpp: In member function 'void CMax6956Io::Init(unsigned char, unsigned char, unsigned int)':
/home/.../mystuff/domoproject/lib/i2cdevs/max6956io.cpp:26:30: error: no matching function for call to 'CMax6956Io::SetI2cSlaveAddress(unsigned char&)'
/home/.../mystuff/domoproject/lib/i2cdevs/max6956io.cpp:26:30: note: candidate is:
In file included from /home/geertvc/mystuff/domoproject/lib/i2cdevs/../../include/i2cdevs/max6956io.h:35:0,
from /home/geertvc/mystuff/domoproject/lib/i2cdevs/max6956io.cpp:1:
/home/.../mystuff/domoproject/lib/i2cdevs/../../include/i2chal/i2chal.h:65:9: note: int CI2cHal::SetI2cSlaveAddress(unsigned char, bool)
/home/.../mystuff/domoproject/lib/i2cdevs/../../include/i2chal/i2chal.h:65:9: note: candidate expects 2 arguments, 1 provided
make[2]: *** [lib/i2cdevs/CMakeFiles/i2cdevs.dir/max6956io.cpp.o] Error 1
make[1]: *** [lib/i2cdevs/CMakeFiles/i2cdevs.dir/all] Error 2
make: *** [all] Error 2
But when I added the default parameter in the header file of the base class:
int SetI2cSlaveAddress( UCHAR addr, bool force = false );
and removed it from the source file of the base class:
int CI2cHal::SetI2cSlaveAddress( UCHAR addr, bool force )
then the compiler was happy and all code worked as expected (I could give one or two parameters to the function SetI2cSlaveAddress())!
So, not only for the user of a class it's important to put the default value of a parameter in the header file, also compiling and functional wise it apparently seems to be a must!
If the functions are exposed - non-member, public or protected - then the caller should know about them, and the default values must be in the header.
If the functions are private and out-of-line, then it does make sense to put the defaults in the implementation file because that allows changes that don't trigger client recompilation (a sometimes serious issue for low-level libraries shared in enterprise scale development). That said, it is definitely potentially confusing, and there is documentation value in presenting the API in a more intuitive way in the header, so pick your compromise - though consistency's the main thing when there's no compelling reason either way.
One more point I haven't found anyone mentioned:
If you have virtual method, each declaration can have its own default value!
It depends on the interface you are calling which value will be used.
Example on ideone
struct iface
{
virtual void test(int a = 0) { std::cout << a; }
};
struct impl : public iface
{
virtual void test(int a = 5) override { std::cout << a; }
};
int main()
{
impl d;
d.test();
iface* a = &d;
a->test();
}
It prints 50
I strongly discourage you to use it like this
the declaration is generally the most 'useful', but that depends on how you want to use the class.
both is not valid.
Good question...
I find that coders typically use the declaration to declare defaults. I've been held to one way (or warned) or the other too based on the compiler
void testFunct(int nVal1, int nVal2=500);
void testFunct(int nVal1, int nVal2)
{
using namespace std;
cout << nVal1 << << nVal2 << endl;
}
You may do in either (according to standard), but remember, if your code is seeing the declaration without default argument(s) before the definition that contains default argument, then compilation error can come.
For example, if you include header containing function declaration without default argument list, thus compiler will look for that prototype as it is unaware of your default argument values and hence prototype won't match.
If you are putting function with default argument in definition, then include that file but I won't suggest that.
Adding one more point. Function declarations with default argument should be ordered from right to left and from top to bottom.
For example in the below function declaration if you change the declaration order then the compiler gives you a missing default parameter error. Reason the compiler allows you to separate the function declaration with default argument within the same scope but it should be in order from RIGHT to LEFT (default arguments) and from TOP to BOTTOM(order of function declaration default argument).
//declaration
void function(char const *msg, bool three, bool two, bool one = false);
void function(char const *msg, bool three = true, bool two, bool one); // Error
void function(char const *msg, bool three, bool two = true, bool one); // OK
//void function(char const *msg, bool three = true, bool two, bool one); // OK
int main() {
function("Using only one Default Argument", false, true);
function("Using Two Default Arguments", false);
function("Using Three Default Arguments");
return 0;
}
//definition
void function(char const *msg, bool three, bool two, bool one ) {
std::cout<<msg<<" "<<three<<" "<<two<<" "<<one<<std::endl;
}
There are a few legal ways which can we declare a function in C++.
Some of the legal ways are:
void function ();
void function (void);
dataType function (dataType);
and so on...
Recently, I came across a function declaration as such:
void (function) (); //Take note of the braces around the function name
I have never seen somehting like this before, when I tested it in a C++ compiler, it runs without any warning or compilation errors.
My question is: Why is void (function) (); a legal way to decalre a function prototype? Is there any special meaning to declare a function in this way? Or does it just work normally like any other function declaration?
One difference is that enclosing it in parenthesis prevents the function-like macros expansion by the preprocessor. As mentioned in the other answers it makes no difference though to the actual compiler.
For instance:
// somewhere buried deep in a header
#define function(a, b) a + b
// your code
void function() { // this expands the macro and gives compilation error
}
void (function)() { // this does not expand and works as expected
}
This comes in handy for instance when the bright minds behind the Microsoft Visual Studio library decided to provide function-like macros for things like min and max. (There are other ways like #undef to go around this).
Note that object-like macros (e.g. #define function 3 + 4) are still expanded.
The preprocessor is just a dumb text replacement tool (as opposed to the compiler which is just a (smart) text replacement tool). It takes the macro definition and replaces it everywhere. He is not aware of the semantics of what he replaces.
For instance:
// somewhere buried deep in a header
#define function 3 + 2
// your code
void function() {
}
The preprocessor sees the word function and textually replaces it with the string 3 + 2. He is unaware that function is a id-name part of a function declaration and definition. After the preprocess phase there come the actual compile phases. So the compiler actually sees:
// your code
void 3 + 2() {
}
which does not make any sense to him and gives an error.
For function-like macros
// somewhere buried deep in a header
#define function(a, b) a + b
The preprocessor does the same except that it expects two ‘tokens’ enclosed in parenthesis separated by comma (the parameters) and does the replacement. (again no semantics aware):
int d = function(2, 3);
//will be replaced by the preprocessor to:
int d = 2 + 3; // passes compilation phase
void function();
// the preprocessor doesn’t find the arguments for function so it gives an error.
However if it encounters (function) it will not try to expand it (it ignores it). It is just a rule.
it's the same as
void function();
you can declare it as
void ((function)) ();
if you want :)
be careful not to mix this up with the function pointer declaration syntax.
There is nothing special about it, it means exactly the same as the version without parentheses. It is just an artifact of how the syntax is declared. Usually you see the use of parentheses around the function name when a function pointer is declared, e.g.
void (*function_pointer)() = nullptr;
// a function pointer to a function taking and returning void
in contrast to
void *function();
// a function declaration of a function taking void and returning void*
I think it works the same as a normal function because function pointers are declared like: void (*function)() so if you leave out the * then it should be just a function.
It corresponds to the C++ grammar. If to simplify then one of the rules for defining of the declarator looks as
declarator:
(declarator)
So you can write for example
void (function) ();
or
void ( (function) () );
or even the following way
struct A
{
void ( ( function )() const );
};
I think you may find that was:
void (*function) ();
since there is no benefit to using void (function)(); or void (((((function)))))(); for that matter, they're equivalent. If I'm mistaken and it's not a typo, the answer is that you can put as many parentheses around the function name as you like, subject to compiler limitations, as per the code for output6() below.
If I'm not mistaken, that one with the * actually declares a function pointer which can be used to hold a pointer to a function. It does not declare a function at all, just a pointer that can be used to reference a function.
Like an int pointer (for example), the function pointer can point to an arbitrary function, parameters notwhithstanding.
So for example:
#include <iostream>
void (((((output6)))))() { std::cout << 6; }
void output7() { std::cout << 7; }
void output8() { std::cout << 8; }
void (*fn)();
int main() {
fn = &output6; fn();
fn = &output7; fn();
fn = &output8; fn();
std::cout << '\n';
}
would output 678.
This question already has answers here:
Default value of function parameter
(5 answers)
Closed 5 years ago.
What's the place for the default parameter value? Just in function definition, or declaration, or both places?
Default parameter values must appear on the declaration, since that is the only thing that the caller sees.
EDIT: As others point out, you can have the argument on the definition, but I would advise writing all code as if that wasn't true.
You can do either, but never both. Usually you do it at function declaration and then all callers can use that default value. However you can do that at function definition instead and then only those who see the definition will be able to use the default value.
C++ places the default parameter logic in the calling side, this means that if the default value expression cannot be computed from the calling place, then the default value cannot be used.
Other compilation units normally just include the declaration so default value expressions placed in the definition can be used only in the defining compilation unit itself (and after the definition, i.e. after the compiler sees the default value expressions).
The most useful place is in the declaration (.h) so that all users will see it.
Some people like to add the default value expressions in the implementation too (as a comment):
void foo(int x = 42,
int y = 21);
void foo(int x /* = 42 */,
int y /* = 21 */)
{
...
}
However, this means duplication and will add the possibility of having the comment out of sync with the code (what's worse than uncommented code? code with misleading comments!).
Although this is an "old" thread, I still would like to add the following to it:
I've experienced the next case:
In the header file of a class, I had
int SetI2cSlaveAddress( UCHAR addr, bool force );
In the source file of that class, I had
int CI2cHal::SetI2cSlaveAddress( UCHAR addr, bool force = false )
{
...
}
As one can see, I had put the default value of the parameter "force" in the class source file, not in the class header file.
Then I used that function in a derived class as follows (derived class inherited the base class in a public way):
SetI2cSlaveAddress( addr );
assuming it would take the "force" parameter as "false" 'for granted'.
However, the compiler (put in c++11 mode) complained and gave me the following compiler error:
/home/.../mystuff/domoproject/lib/i2cdevs/max6956io.cpp: In member function 'void CMax6956Io::Init(unsigned char, unsigned char, unsigned int)':
/home/.../mystuff/domoproject/lib/i2cdevs/max6956io.cpp:26:30: error: no matching function for call to 'CMax6956Io::SetI2cSlaveAddress(unsigned char&)'
/home/.../mystuff/domoproject/lib/i2cdevs/max6956io.cpp:26:30: note: candidate is:
In file included from /home/geertvc/mystuff/domoproject/lib/i2cdevs/../../include/i2cdevs/max6956io.h:35:0,
from /home/geertvc/mystuff/domoproject/lib/i2cdevs/max6956io.cpp:1:
/home/.../mystuff/domoproject/lib/i2cdevs/../../include/i2chal/i2chal.h:65:9: note: int CI2cHal::SetI2cSlaveAddress(unsigned char, bool)
/home/.../mystuff/domoproject/lib/i2cdevs/../../include/i2chal/i2chal.h:65:9: note: candidate expects 2 arguments, 1 provided
make[2]: *** [lib/i2cdevs/CMakeFiles/i2cdevs.dir/max6956io.cpp.o] Error 1
make[1]: *** [lib/i2cdevs/CMakeFiles/i2cdevs.dir/all] Error 2
make: *** [all] Error 2
But when I added the default parameter in the header file of the base class:
int SetI2cSlaveAddress( UCHAR addr, bool force = false );
and removed it from the source file of the base class:
int CI2cHal::SetI2cSlaveAddress( UCHAR addr, bool force )
then the compiler was happy and all code worked as expected (I could give one or two parameters to the function SetI2cSlaveAddress())!
So, not only for the user of a class it's important to put the default value of a parameter in the header file, also compiling and functional wise it apparently seems to be a must!
If the functions are exposed - non-member, public or protected - then the caller should know about them, and the default values must be in the header.
If the functions are private and out-of-line, then it does make sense to put the defaults in the implementation file because that allows changes that don't trigger client recompilation (a sometimes serious issue for low-level libraries shared in enterprise scale development). That said, it is definitely potentially confusing, and there is documentation value in presenting the API in a more intuitive way in the header, so pick your compromise - though consistency's the main thing when there's no compelling reason either way.
One more point I haven't found anyone mentioned:
If you have virtual method, each declaration can have its own default value!
It depends on the interface you are calling which value will be used.
Example on ideone
struct iface
{
virtual void test(int a = 0) { std::cout << a; }
};
struct impl : public iface
{
virtual void test(int a = 5) override { std::cout << a; }
};
int main()
{
impl d;
d.test();
iface* a = &d;
a->test();
}
It prints 50
I strongly discourage you to use it like this
the declaration is generally the most 'useful', but that depends on how you want to use the class.
both is not valid.
Good question...
I find that coders typically use the declaration to declare defaults. I've been held to one way (or warned) or the other too based on the compiler
void testFunct(int nVal1, int nVal2=500);
void testFunct(int nVal1, int nVal2)
{
using namespace std;
cout << nVal1 << << nVal2 << endl;
}
You may do in either (according to standard), but remember, if your code is seeing the declaration without default argument(s) before the definition that contains default argument, then compilation error can come.
For example, if you include header containing function declaration without default argument list, thus compiler will look for that prototype as it is unaware of your default argument values and hence prototype won't match.
If you are putting function with default argument in definition, then include that file but I won't suggest that.
Adding one more point. Function declarations with default argument should be ordered from right to left and from top to bottom.
For example in the below function declaration if you change the declaration order then the compiler gives you a missing default parameter error. Reason the compiler allows you to separate the function declaration with default argument within the same scope but it should be in order from RIGHT to LEFT (default arguments) and from TOP to BOTTOM(order of function declaration default argument).
//declaration
void function(char const *msg, bool three, bool two, bool one = false);
void function(char const *msg, bool three = true, bool two, bool one); // Error
void function(char const *msg, bool three, bool two = true, bool one); // OK
//void function(char const *msg, bool three = true, bool two, bool one); // OK
int main() {
function("Using only one Default Argument", false, true);
function("Using Two Default Arguments", false);
function("Using Three Default Arguments");
return 0;
}
//definition
void function(char const *msg, bool three, bool two, bool one ) {
std::cout<<msg<<" "<<three<<" "<<two<<" "<<one<<std::endl;
}