I have a case where lookup and overload resolution behaves differently:
for user-defined class vs built-in types vs std::string
for direct call vs function pointer call
I cannot figure what exact parts of the standard justify these differences.
Consider the following C++11 code:
#include <iostream>
#include <string>
using namespace std;
struct Test1 {};
struct Test2 {};
template<typename T>
int f(T t) { return 0; }
int f(Test1 t) { return 10; }
int f(int y) { return 20; }
template<typename T>
int use1() { return f(T()); }
template<typename T>
int use2() { auto fp = static_cast<int(*)(T)>(&f); return (*fp)(T()); }
int f(Test2 t) { return 30; }
int f(string s) { return 40; }
int f(double y) { return 50; }
int main() {
cout << "use1<float>: " << use1<float>() << endl;
cout << "use1<Test1>: " << use1<Test1>() << endl;
cout << "use1<int>: " << use1<int>() << endl;
cout << "use1<Test2>: " << use1<Test2>() << endl;
cout << "use1<string>: " << use1<string>() << endl;
cout << "use1<double>: " << use1<double>() << endl;
cout << endl;
cout << "use2<float>: " << use2<float>() << endl;
cout << "use2<Test1>: " << use2<Test1>() << endl;
cout << "use2<int>: " << use2<int>() << endl;
cout << "use2<Test2>: " << use2<Test2>() << endl;
cout << "use2<string>: " << use2<string>() << endl;
cout << "use2<double>: " << use2<double>() << endl;
return 0;
}
Output is (same with g++ 6.3 and clang++5.0.0 trunk):
use1<float>: 0
use1<Test1>: 10
use1<int>: 20
use1<Test2>: 30
use1<string>: 0
use1<double>: 0
use2<float>: 0
use2<Test1>: 10
use2<int>: 20
use2<Test2>: 0
use2<string>: 0
use2<double>: 0
Questions:
Why use1<string> is different from use1<Test2> ? Both types are declared "at the top", both f() overloads are declared at the bottom.
Why use1<Test2> is different from use1<double>? Corresponding f() overloads are on adjacent lines, is there anything special in treatment of built-in types?
Why use1<Test2> is different from use2<Test2>? The type of a pointer to function in use2 seems to match the calling context in use1.
Two-phase name lookup. At the point where use1 is defined, three overloads of f are visible via normal lookup. At the point of instantiation, additional overloads may be found - but only by argument-dependent lookup. Test2 is in global namespace, so f(Test2) is found by ADL; whereas string is in namespace std, and so f(string) (which is, obviously, not in namespace std) is not found by ADL. double has no associated namespaces, and so ADL doesn't kick in at all.
In use2, f is not a dependent name, and so the second-phase lookup is not performed at all - only overloads visible at the point of definition are considered.
Related
This question already has answers here:
Where to put default parameter value in C++? [duplicate]
(10 answers)
Default value of function parameter
(5 answers)
Closed 1 year ago.
I want to know how do u declare a function with definite arguments. It's said to be good practice to put the function declaration at the beginning , before the main() function and then its definition, but in this case the compiler gives me an error, becase it's like if it doesn't see the formal arguments.
#include <iostream>
using namespace std;
void function(int i=1, char a='A', float val=45.7);
int main()
{
function();
return 0;
}
void function(int i = 1, char a='A', float val=45.7)
{
cout << "i: " << i << endl;
cout << "a: " << a << endl;
cout << "val: " << val << endl;
}
I tried to insert the formal arguments in the declaration, but it doesn't work.
You can put predefined arguments either in the forward declaration or in the function parameter, but not both
If your function has a forward declaration, you really should only have predefined arguments in the forward declaration, not in the function parameter.
Change that to:
void function(int i, char a, float val)
{
// you shouldn't use using namespace std;
std::cout << "i: " << i << '\n'; // notice the use of newline character instead of std::endl
std::cout << "a: " << a << '\n';
std::cout << "val: " << val << '\n';
}
here is the way to initialise the function args to default values.
You dont need to pass default args in defination. They should be given only in the declaration itself.
#include <iostream>
using namespace std;
void function(int i=1, char a='A', float val=45.7);
int main()
{
function();
return 0;
}
void function(int i, char a, float val)
{
cout << "i: " << i << endl;
cout << "a: " << a << endl;
cout << "val: " << val << endl;
}
Now, this code will work like a charm.
Link to working example -> http://cpp.sh/4j7lx
First off: I know that it is generally a bad idea to change an object's class, but I'm implementing my own programming language, and it has variables that can contain values of any type, and even change their type at will, so please assume I'm not a beginner not understanding OO basics.
Currently, I implement my variant variables in C. Each one has a pointer to a table of function pointers, containing functions like SetAsInt(), SetAsString() etc., followed by what would be instance variables in C++. All objects are the same size.
When a variable contains a string and someone assigns an Int to it, I manually call the destructor, change the table of function pointers to point to the table used for variadic int values, and then set its int instance variable.
This is a bit hard to maintain, as every time I add a new type, I have to add a new table of function pointers and fill out all the function pointers in it. Structs of function pointers seem to be very badly type-checked, and missing fields don't lead to complaints, so I can easily accidentally forget one pointer in the list and get interesting crashes. Also, I have to repeat all the function pointers that are the same in most types.
I'd like to implement my variadic types in C++ instead, where a lot of this type-checking and inheriting default behaviours is done for me by the compiler. Is there a safe way to do this?
PS - I know I could create a wrapper object and use new to allocate a new object, but I can't have the additional extra allocation overhead for every int variable on the stack.
PPS - The code needs to be portable across Linux, Mac, iOS and Windows for now, but if someone has a standard C++ solution, that would be even better.
PPPS - The list of types is extensible, but predetermined at compile-time. The base layer of my language defines just the basic types, but the host application my language is compiled into adds a few more types.
Usage Example:
CppVariant someNum(42); // Creates it as CppVariantInt.
cout << "Original int: " << someNum->GetAsInt()
<< " (" << someNum->GetAsDouble() << ")" << endl;
someNum->SetAsInt(700); // This is just a setter call.
cout << "Changed int: " << someNum->GetAsInt()
<< " (" << someNum->GetAsDouble() << ")" << endl;
someNum->SetAsDouble(12.34); // This calls destructor on CppVariantInt and constructor on CppVariantDouble(12.34).
cout << "Converted to Double: " << someNum->GetAsInt()
<< " (" << someNum->GetAsDouble() << ")" << endl; // GetAsInt() on a CppVariantDouble() rounds, or whatever.
(Imagine that beyond double and int, there would be other types in the future, like strings or booleans, but the caller of GetAsInt()/SetAsInt() shouldn't have to know what it is stored as, as long as it can be converted at runtime)
Here is a solution based on type-erasure, union and template specializations.
I'm not sure it fits your requirements.
Anyway, here is what it gets:
Anything is placed on the dynamic storage
No hierarchy required
You can easily improve it further to reduce the amount of code, but this aims to serve as a base point from which to start.
It follows a minimal, working example based on the intended use in the question:
#include<iostream>
class CppVariant {
union var {
var(): i{0} {}
int i;
double d;
};
using AsIntF = int(*)(var);
using AsDoubleF = double(*)(var);
template<typename From, typename To>
static To protoAs(var);
public:
CppVariant(int);
CppVariant(double);
int getAsInt();
double getAsDouble();
void setAsInt(int);
void setAsDouble(double);
private:
var data;
AsIntF asInt;
AsDoubleF asDouble;
};
template<>
int CppVariant::protoAs<int, int>(var data) {
return data.i;
}
template<>
int CppVariant::protoAs<double, int>(var data) {
return int(data.d);
}
template<>
double CppVariant::protoAs<int, double>(var data) {
return double(data.i);
}
template<>
double CppVariant::protoAs<double, double>(var data) {
return data.d;
}
CppVariant::CppVariant(int i)
: data{},
asInt{&protoAs<int, int>},
asDouble{&protoAs<int, double>}
{ data.i = i; }
CppVariant::CppVariant(double d)
: data{},
asInt{&protoAs<double, int>},
asDouble{&protoAs<double, double>}
{ data.d = d; }
int CppVariant::getAsInt() { return asInt(data); }
double CppVariant::getAsDouble() { return asDouble(data); }
void CppVariant::setAsInt(int i) {
data.i = i;
asInt = &protoAs<int, int>;
asDouble = &protoAs<int, double>;
}
void CppVariant::setAsDouble(double d) {
data.d = d;
asInt = &protoAs<double, int>;
asDouble = &protoAs<double, double>;
}
int main() {
CppVariant someNum(42);
std::cout << "Original int: " << someNum.getAsInt() << " (" << someNum.getAsDouble() << ")" << std::endl;
someNum.setAsInt(700);
std::cout << "Changed int: " << someNum.getAsInt() << " (" << someNum.getAsDouble() << ")" << std::endl;
someNum.setAsDouble(12.34);
std::cout << "Converted to Double: " << someNum.getAsInt() << " (" << someNum.getAsDouble() << ")" << std::endl;
}
On a lark, I tried using placement new to do this, and I have ... something ... It compiles, it does the job, but I'm not sure if it's an improvement over pure C. Since I can't have a union of C++ objects, I create a CPPVMAX() macro to pass the largest sizeof() of all subclasses as the size to mBuf[], but that's not really pretty either.
#include <iostream>
#include <string>
#include <cmath>
#define CPPVMAX2(a,b) (((a) > (b)) ? (a) : (b))
#define CPPVMAX3(a,b,c) CPPVMAX2((a),CPPVMAX2((b),(c)))
using namespace std;
class CppVariantBase
{
public:
CppVariantBase() { cout << "CppVariantBase constructor." << endl; }
virtual ~CppVariantBase() { cout << "CppVariantBase destructor." << endl; }
virtual int GetAsInt() = 0;
virtual double GetAsDouble() = 0;
virtual void SetAsInt( int n );
virtual void SetAsDouble( double n );
};
class CppVariantInt : public CppVariantBase
{
public:
CppVariantInt( int n = 0 ) : mInt(n)
{
cout << "CppVariantInt constructor." << endl;
}
~CppVariantInt() { cout << "CppVariantInt destructor." << endl; }
virtual int GetAsInt() { return mInt; }
virtual double GetAsDouble() { return mInt; }
virtual void SetAsInt( int n ) { mInt = n; }
protected:
int mInt;
};
class CppVariantDouble : public CppVariantBase
{
public:
CppVariantDouble( double n = 0 ) : mDouble(n)
{
cout << "CppVariantDouble constructor." << endl;
}
~CppVariantDouble()
{
cout << "CppVariantDouble destructor." << endl;
}
virtual int GetAsInt()
{
if( int(mDouble) == mDouble )
return mDouble;
else
return round(mDouble);
}
virtual double GetAsDouble() { return mDouble; }
virtual void SetAsDouble( int n ) { mDouble = n; }
protected:
double mDouble;
};
class CppVariant
{
public:
CppVariant( int n = 0 ) { new (mBuf) CppVariantInt(n); }
~CppVariant() { ((CppVariantBase*)mBuf)->~CppVariantBase(); }
operator CppVariantBase* () { return (CppVariantBase*)mBuf; }
CppVariantBase* operator -> () { return (CppVariantBase*)mBuf; }
protected:
uint8_t mBuf[CPPVMAX3(sizeof(CppVariantBase),sizeof(CppVariantInt),sizeof(CppVariantDouble))];
};
void CppVariantBase::SetAsInt( int n )
{
this->~CppVariantBase();
new (this) CppVariantInt(n);
}
void CppVariantBase::SetAsDouble( double n )
{
this->~CppVariantBase();
new (this) CppVariantDouble(n);
}
int main(int argc, const char * argv[]) {
CppVariant someNum(42);
cout << "Original int: " << someNum->GetAsInt()
<< " (" << someNum->GetAsDouble() << ")" << endl;
someNum->SetAsInt(700); // This is just a setter call.
cout << "Changed int: " << someNum->GetAsInt()
<< " (" << someNum->GetAsDouble() << ")" << endl;
someNum->SetAsDouble(12.34); // This changes the class to CppVariantDouble.
cout << "Converted to Double: " << someNum->GetAsInt()
<< " (" << someNum->GetAsDouble() << ")" << endl;
return 0;
}
I'm trying to make something in C++ and I have a problem. I have this code:
#include <iostream>
#include <string>
//---MAIN---
using namespace std;
int af1 = 1;
int af2 = 1;
void lettersort(int cnt1) {
cout << "RESULT:" << cnt1 << endl;
cnt1++;
cout << "RESULT WHEN+:" << cnt1 << endl;
cout << "RESULT IN GLOBAL INT:" << af2 << endl;
}
int main()
{
lettersort(af2);
return 0;
}
So is there any way so that cnt1++ affects af2 too, to make it bigger ? I don't want to use af2++ directly because I want to sometimes use af1.
At the moment you are just passing af2 to cnt1 by value, so any changes to cnt1 are strictly local to the function lettersort. In order to get the behaviour you want you need to pass your cnt1 parameter by reference. Change:
void lettersort(int cnt1)
to:
void lettersort(int &cnt1)
You are passing the argument by value. I.e., you are copying the value of af1 to a local variable in lettersort. This integer is then incremented, and disposed of when the function ends, without affecting the original af1. If you want the function to be able to affect af1, you should pass the argument by reference:
void lettersort(int& cnt1) { // Note the "&"
if i understood your question:
there are 2 ways you can do that.
make lettersort function return the new value, and put it in af2
int lettersort(int cnt1) {
cout << "RESULT:" << cnt1 << endl;
cnt1++;
cout << "RESULT WHEN+:" << cnt1 << endl;
cout << "RESULT IN GLOBAL INT:" << af2 << endl;
return cnt1;
}
int main()
{
af2 = lettersort(af2);
return 0;
}
pass the value by reference. you can read about it here, but generally its about passing a pointer to that value. meaning whatever you do on the argument you are passing, will happen on the original var.
example:
void foo(int &y) // y is now a reference
{
using namespace std;
cout << "y = " << y << endl;
y = 6;
cout << "y = " << y << endl;
} // y is destroyed here
int main()
{
int x = 5;
cout << "x = " << x << endl;
foo(x);
cout << "x = " << x << endl;
return 0;
}
here you have to just modified the argument pass to lettersort
function as passed by reference.
for example if you declare and initialize any variable like:
int a=10; int &b = a;
now a and b refer to the same value.if you change a then the changes
also reflect in b also.
so,
cout << a; cout << b;
both statement produce the same result across the program. so using
this concept i modified the function argument and made it as by
reference.
your correct code is :
#include <iostream>
#include <string>
using namespace std;
int af1 = 1;
int af2 = 1;
void lettersort(int &cnt1) {
cout << "RESULT:" << cnt1 << endl;
cnt1++;
cout << "RESULT WHEN+:" << cnt1 << endl;
cout << "RESULT IN GLOBAL INT:" << af2 << endl;
}
int main()
{
lettersort(af2);
return 0;
}
I started learning about templates and I copied the code from my book but the compiler is giving me this error
Error 1 error: 'swap' : ambiguous call to overloaded function"
Here is my program
#include <iostream>
template <typename X>
void swap(X &a, X &b);
int _tmain(){
using namespace std;
int a, b;
cout << "enter two numbers:\n";
cin >> a >> b;
cout << "Your numbers are: " << a << ", " << b << endl;
swap(a, b); //error is here
cout << "Your numbers reversed are: " << a << ", " << b << endl;
return 0;
}
template <typename X>
void swap(X &a, X &b){
X temp = a;
a = b;
b = temp;
}
You are redefining the function swap with the same signature, so you're having an ambiguous definition of it, and, consequently, an ambiguous call.
If you want to maintain the function with the same signature, you should either choose to use not the "using namespace std;", which will not shadow your swap() definition, or simply define tthe function in another namespace.
Example:
namespace your_namespace {
template <typename X>
void swap(X &a, X &b) {
X temp = a;
a = b;
b = temp;
}
}
int foo(10), bar(20);
std::cout << "foo: " << foo << "; bar: " << bar << std::endl;
your_namespace::swap(foo, bar);
std::cout << "foo: " << foo << "; bar: " << bar << std::endl;
Output:
foo: 10; bar: 20
foo: 20; bar: 10
Regards!
Just out of curiosity: if I have nested scopes, like in this sample C++ code
using namespace std;
int v = 1; // global
int main (void)
{
int v = 2; // local
{
int v = 3; // within subscope
cout << "subscope: " << v << endl;
// cout << "local: " << v << endl;
cout << "global: " << ::v << endl;
}
cout << "local: " << v << endl;
cout << "global: " << ::v << endl;
}
Is there any way to access the variable v with the value 2 from the "intermediate" scope (neither global nor local)?
You can declare a new reference as an alias like so
int main (void)
{
int v = 2; // local
int &vlocal = v;
{
int v = 3; // within subscope
cout << "local: " << vlocal << endl;
}
}
But I would avoid this practice this altogether. I have spent hours debugging such a construct because a variable was displayed in debugger as changed because of scope and I couldn't figure out how it got changed.
The answer is No You cannot.
A variable in local scope shadows the variable in global scope and the language provides a way for accessing the global variable by using qualified names of the global like you did. But C++ as an language does not provide anyway to access the intermediate scoped variable.
Considering it would have to be allowed it would require a lot of complex handling, Imagine of the situation with n number of scopes(could very well be infinite) and handling of those.
You are better off renaming your intermediate variables and using those that would be more logical and easy to maintain.
There are two types of scope resolution operators in C++ - unary scope and a class scope. There is no function scope or "any particular parent scope" resolution operators. That makes it impossible to solve your problem, as it is, in general because you cannot refer to anonymous scopes. However, you can either create an alias, rename variables, or make this a part of the class, which of course implies a code change. This is the closest I can get you without renaming in this particular case:
#include <iostream>
using namespace std;
int v = 1; // global
class Program
{
static int v; // local
public:
static int main ()
{
int v = 3; // within subscope
cout << "subscope: " << v << endl;
cout << "local: " << Program::v << endl;
cout << "global: " << ::v << endl;
}
};
int Program::v = 2;
int main ()
{
return Program::main ();
}
There are other ways, like making sure that variables are not optimized out and are on stack, then you can work with stack directly to get the value of the variable you want, but let's not go that way.
Hope it helps!
You could fake it like this:
#include <iostream>
using namespace std;
int v = 1;
int main()
{
int v = 2;
{
int &rv = v; // create a reference
int v = 3; // then shadow it
cout << "subscope: " << v << endl;
cout << "local: " << rv << endl;
cout << "global: " << ::v << endl;
}
cout << "local: " << v << endl;
cout << "global: " << ::v << endl;
return 0;
}
Interestingly this compiles on cygwin g++ but segfaults if you try to run it:
#include <iostream>
using namespace std;
int v = 1;
int main()
{
int v = 2;
{
int &v = v;
cout << "subscope: " << v << endl;
// cout << "local: " << v << endl;
cout << "global: " << ::v << endl;
}
cout << "local: " << v << endl;
cout << "global: " << ::v << endl;
return 0;
}