I expected the following program to print "11" but it actually prints "01" so it seems like the first assignment fails.
struct A
{
A(int i = 0) : i_(i) {}
int i_;
};
int main()
{
A x(1);
A y;
static_cast<A>(y) = x; // *** Fails to assign ***
std::printf("%i", y.i_);
y = x;
std::printf("%i", y.i_);
}
If I use a primitive type likeint instead of A then int x = 1; int y; static_cast<int>(y) = x; does assign the value 1 to x. Is there some way I can get it to work for custom types? I tried adding operator A() { return *this; } to struct A but that didn't work.
Obviously this is a stupid program but the problem arises in a template function where I have static_cast<std::remove_const<T>::type>(y) = x and it was working fine for primitive types but just now failed for a custom type.
As with any cast, static_cast<A>(y) is a temporary copy of y. You can cast to a reference type instead (static_cast<A&>(y)); more generally, you could achieve this with std::add_lvalue_reference.
For the more specific example you described, you'll need const_cast rather than static_cast, but the basic principle is the same.
Here's an example that compiles, but has UB because of the modification of a const object (and thus returns 0, not 42). Without knowing more about what you're trying to do, I shan't attempt to disguise that for the purposes of this example:
#include <iostream>
#include <type_traits>
template <typename T>
T foo(T val)
{
T x{};
using not_const = typename std::remove_const<T>::type;
using ref_type = typename std::add_lvalue_reference<not_const>::type;
const_cast<ref_type>(x) = val;
return x;
}
int main()
{
std::cout << foo<const int>(42) << '\n';
}
Related
I would like to declare an alternative way to access a class member (an array position specifically), as in
class Foo {
int a[2];
int &a_first = a[0];
};
such that any access to a_first in a Foo instance is for all purposes equivalent to accessing a[0] of that same instance.
The code above works as I expected with singular instances and single vectors of the class, but when used on a nested vector the reference address differs from the member address:
#include <iostream>
#include <vector>
class A {
public:
int m;
int &mref = m;
};
int main()
{
A a;
std::cout << (&a.m == &a.mref) << '\n'; // output: 1
std::vector<A> av1(1);
std::cout << (&av1[0].m == &av1[0].mref) << '\n'; // output: 1
std::vector<std::vector<A>> av2(1, std::vector<A>(1));
std::cout << (&av2[0][0].m == &av2[0][0].mref) << '\n'; // output: 0
return 0;
}
I thought reference variables acted as aliases of their assigned variable and were resolved at compile time without being assigned any actual memory at runtime, unlike pointers. Why is this not consistent with the behavior displayed above? What would be a correct way to achieve the alias I want?
The code above works as I expected
Actually it doesn't:
class A {
public:
int m{};
int &mref = m;
};
int main()
{
A a;
A a2 = a;
std::cout << (&a2.m == &a2.mref) << '\n'; // output: 0
};
A reference can be bound only on initialization. Copying will copy the value, not re-bind the reference. So any copy of an object of type A will mess up your reference. This is what happens in your nested vector example. You don't need a nested vector to see this. Try and push in a vector<A>, the vector will have to resize and during the resize will copy its elements, messing your reference.
I thought reference variables acted as aliases of their assigned variable ...
True
... and were resolved at compile time without being assigned any actual memory at runtime, unlike pointers.
Not always. You cannot always resolve at compile time the reference, in which case the reference will actually be implemented with a pointer behind the scenes.
Possible solutions:
use std::reference_wrapper, the copy assignment operator rebinds the reference, but you will need to implement custom copy constructor/assignments for your class:
class A {
public:
int m{};
std::reference_wrapper<int> mref = m;
A() = default;
A(const A& other) noexcept
: m{other.m},
mref{m}
{}
A& operator=(const A& other) noexcept
{
m = other.m;
mref = m;
return *this;
}
};
use a method that returns a reference to the variable
class A {
public:
int m{};
int& mref() { return m; }
const int& mref() const { return m; }
};
I am trying to write a general integral function and I would like to implement it in such a way so that it can accept any mathematical function. That is, I would like to pass the math function as an input parameter. In pseudo-code: simpson_int(x*x). I've heard of the function template in <functional> but I don't really have experience with templates in C++.
There are some solutions that comes in my mind (and this is my approach at the problem, for sure there are more solution, and maybe what I'm pointing out is not the best), that consider the fact that you need to call the argument function more than once in the Simpson implementation (thus you need a "callable" argument):
Function pointer
Function pointers (more C than C++), where you declare with two arguments: the first one will be the pointer to a function with the specified types, while the second is the argument for your function. Lets
make an example:
#include <iostream>
double power2(double x) {
return x * x;
}
double simspon(double (*f)(double), double x) {
return f(x);
}
int main() {
std::cout << simspon(power2, 2);
return 0;
}
In this case I have used no templates for reaching the result. But this will not take any function as first argument, but only a function that has as argument a double and returns a double.
I think that most of c++ programmer will suggest you to avoid this method.
Function pointer and templates
So you maybe want to expand the previous example using templates and making it more general. It is quite simple to redefine the function
to accept a template (an abstract type) that you actually specify only when you use it in your code:
#include <iostream>
double power2(double x) {
return x * x;
}
int power2int(int x) {
return x * x;
}
template <class T, class P>
P simspon(T (*f)(P), P x) {
return f(x);
}
int main() {
std::cout << simspon<double, double>(power2, 2.0);
std::cout << simspon<int, int>(power2int, 2);
return 0;
}
T and P are two templates: the first one is used for describing the returned value of the function pointer, while the second specify the argument of the function pointer, and the returned value of simpson.So when you are writing template <class T, classP> you are actually informing the compiler that that you are using T and P as placeholder for different type. You will actually declare the type that you want later on, when you will call the function in the main. This is not good code but I'm building the path to understand templates. Also, you specify the type of your argument function when you actually call simpson, with the < >.
(Disclaimer: you should consider to use template <typename T ...> instead of class. But I'm used with the old class and there are situation in which typename cannot be used, there are a lot of questions on SO that dive into this.)
Using std::function
Instead of using a function pointer as argument you may want to create a variable that stores your function to be passed as argument of simpson. This bring several advantages, because they are actually an object inside your code that have some predictable behavior in some unwanted circumstances (for example, in case of a null function pointer you have to check the pointer itself and handle it, in case of std::function if there is no callable pointer it throws std::bad_function_call error)
Here an example, and it uses again templates, as before:
#include <iostream>
#include <functional>
double power2(double x) {
return x * x;
}
int power2int(int x) {
return x * x;
}
template <class T, class P>
P simspon(std::function<T(P)> f, P x) {
return f(x);
}
int main() {
std::function<double(double)> p_power2 = power2;
std::cout << simspon<double, double>(p_power2, 2.0);
std::function<double(double)> p_power2int = power2int;
std::cout << simspon<int, int>(power2int, 2);
return 0;
}
Using lambdas
lambdas are closure and in your case (if you can use the standard C++14) can be used alongside the auto keyword to achieve quite a general behavior, without the explicit use of templates. The closure are also able to capture part/the whole context, check the reference for this.
Let's see an example, in which I create two lambdas that receive different arguments and a simpson function that is quite general (actually it is not, is the compiler that defines different functions with respect to the call that you do).
#include <iostream>
auto lambda = [](auto x) { return x * x ; };
auto lambda_2 = [] (int x) { return x + 10; };
auto simpson(auto f, auto x) {
return f(x);
}
int main() {
std::cout << simpson(lambda, 2.0);
std::cout << simpson(lambda_2, 1);
return 0;
}
You need to compile it with the -std=c++14 flag. There are tons of advise that comes in my mind to suggest you to avoid to implement your code in this way, remember that it has only some illustrative purposes (I've more than exaggerated with the auto keyword).
Function objects (the Problem class)
Maybe an improvement for your case is to write a general class for the mathematical functions to integrate and pass the object to your function. This bring several advantages: you may want to save some of the integrative result inside your function or even write the stream operator to pretty print your problem. This is the solution employed typically by mathematical libraries.
In this extremely simple case, we have a class that is a problem. When you create a new instance for this class, a std::function is passed to the constructor and stored inside the class. The instance of the class is the argument for your simpson:
#include <iostream>
#include <functional>
template <class T, class P>
class Problem {
public:
// Attributes
std::function<T(P)> _f;
// Constructor
Problem(std::function<T(P)> f) : _f(f) {};
// Making the object callable
P operator()(P x) { return _f(x); }
};
template <class T, class P>
P simspon(Problem<T, P> p, P x) {
return p(x);
}
int main() {
Problem<double, double> prb([](double x) { return x * x; });
std::cout << simspon<double, double>(prb, 2);
return 0;
}
Use std::function, like this for example:
#include <iostream> // std::cout
#include <functional> // std::function
int main()
{
std::function<double(double)> simpson_int =([](double x) { return x * x; };
std::cout << "simpson_int(4): " << simpson_int(4) << '\n';
return 0;
}
which outputs:
simpson_int(4): 16
Let f() be a function that returns a unique_ptr<X> and let m be a member field of X. While f() can be used as an rvalue reference, f()->m cannot, forcing me to use move(f()->m).
Assuming that I can define my own unique_ptr instead of using the existing one, is there a way to make my -> operator keep the rvalue-ness? If this is not recommended, please explain why.
EDIT: To all people telling me to add a getter. I am trying to avoid adding special support in X, I want to do it through the unique_ptr only. Also, your solution can be improved by using a right reference for this as in the following example:
struct X {
SomeType m;
const SomeType &getM() const { return m; }
SomeType &&getM() && { return move(m); }
SomeType &getM() { return m; }
}
As long as you are accessing the value m by name, this can never be an r-value without casting. You could however add a member function which "moves" the member value out of your object.
using IntPtr = std::unique_ptr<int>;
class X {
IntPtr m;
public:
X();
IntPtr getM() { return std::move(m); }
}
Hide the move... (undeleted as I think this could be one way of solving it without having to have your own custom unique_ptr) and I guess it's in keeping with encapsulation...
#include <memory>
#include <iostream>
struct foo
{
std::string m;
std::string m_()
{ return std::move(m); }
};
std::unique_ptr<foo> get_foo()
{ return std::unique_ptr<foo>(new foo{ "Bar" }); }
void bar(std::string&& r)
{ std::cout << r << std::endl; }
int main()
{
// bar(get_foo()->m); // this does not compile
bar(get_foo()->m_()); // this is happy...
}
Now you should be good to go...
decltype fails if the function you're calling it on is overloaded, as in this code:
#include <iostream>
int test(double x, double y);
double test(int x, int y);
char test(char x, int y);
int main()
{
std::cout << decltype(test) << std::endl;
return 0;
}
Results:
error: decltype cannot resolve address of overloaded function
I understand that this is because decltype can't figure out which function you're trying to get the type of. But why isn't there another way to make this work, like this:
std::cout << decltype(test(double, double)) << std::endl;
or this:
double x = 5, y = 2;
std::cout << decltype(test(x, y)) << std::endl;
Since a function cannot be overloaded simply based on return type, wouldn't passing either datatypes or actual variables to the decltype call be enough to tell it which of the overloads it's supposed to examine? What am I missing here?
To figure out the type of the function from the type of the arguments you'd pass, you can "build" the return type by using decltype and "calling" it with those types, and then add on the parameter list to piece the entire type together.
template<typename... Ts>
using TestType = decltype(test(std::declval<Ts>()...))(Ts...);
Doing TestType<double, double> will result in the type int(double, double). You can find a full example here.
Alternatively, you might find the trailing return type syntax more readable:
template<typename... Ts>
using TestType = auto(Ts...) -> decltype(test(std::declval<Ts>()...));
I belive you may be looking for std::result_of<>
cppreference page.
I have found another way: use std::declval to generate a fake object, then use decltype:
#include <type_traits>
#include <functional>
int myfunc(int a)
{
return a;
}
float myfunc(float a)
{
return a;
}
int main()
{
decltype(myfunc(std::declval<float>())) a; // return type
std::function<decltype(a)(float)> fun; // function type
return 0;
}
I'm pretty new to C++ and as an exercise (and perhaps eventually .Net utility) I'm doing a pointer wrapper (actually in C++/CLI, but this applies to C++ as well). This pointer wrapper (called Apont) currently behaves just like a pointer would, as the test below can show, if lines marked 1. and 2. are commented out:
int main(array<System::String ^> ^args)
{
double ia = 10; double ip = 10;
double *p = &ip; // pointer analogy
Apont<double> ^a =
gcnew Apont<double>(ia); // equivalent to what's below, without errors
a = ~ia;/* 1. IntelliSense: expression must have integral or unscoped enum type
error C2440: '=' : cannot convert from 'double' to 'Utilidades::ComNativos::Apont<T> ^'
error C2171: '~' : illegal on operands of type 'double'*/
Console::WriteLine("ip = {0}; *p = {1}; ia = {2}; !a = {3}", ip, *p, ia, !a);
ia = 20; ip = 20;
Console::WriteLine("ip = {0}; *p = {1}; ia = {2}; !a = {3}", ip, *p, ia, !a);
*p = 30; // pointer analogy
a->Valor = 30; // does exacly what's below, without errors
!a = 30;/* 2. IntelliSense: expression must be a modifiable lvalue
error C2106: '=' : left operand must be l-value */
Console::WriteLine("ip = {0}; *p = {1}; ia = {2}; !a = {3}", ip, *p, ia, !a);
//a->Dispose();
Console::ReadKey();
p = nullptr;
return 0;
}
There are two things I don't like here, marked with 1. and 2. in the code comments, before the lines with errors. The operator~ (see 1.) is defined outside Apont, below:
template<typename T> static Apont<T>^% operator ~(T& valor)
{
return gcnew Apont<T>(valor);
}
I think this one has to be defined outside Apont, but I'm not sure. I cannot understand very well the errors it produces (these are, of course, in the use, not in the definition).
To set the value to which the instance of Apont refers I must use a property (the line marked 2. doesn't work, with errors in the setting usage only), Apont::Valor, which is the equivalent to use *p. What I'd like to do is as I use *p to get or set the value it points to, use !a with the same effect on Apont. Here's Apont::operator!()'s current definition:
T operator !()
{
return Valor;
}
As you can see in 2. (comment in the code, before the respective errors), it doesn't work for setting a value. Maybe I should return a reference? Make another operator with the same name, perhaps outside the class? I tried several options, however, I got similar errors, and came out more confused.
The question is: how can I make an operator that behaves like & (in this case, ~) and one that behaves like * (in this case, !, for dereference, but that behaves like Apont::Valor, whose old definition you can see below)?
property T Valor
{
T get()
{
if (pointer != nullptr)
return *pointer;
else if (eliminado && ErroSeEliminado) // means "disposed && ErrorIfDisposed"
throw gcnew ObjectDisposedException("O objeto já foi pelo menos parcialmente eliminadao.");
else if (ErroSeNulo) // means "ErrorIfNull"
throw gcnew NullReferenceException();
else
return 0;
// don't worry, this is not default behavior, it is returned only if you want to ignore all errors and if the pointer is null
}
void set(T valor)
{
*pointer = valor;
}
}
Let me recap in a new answer for clarity.
Solving the ! operator is easy, as I said in my previous answer, just add a reference.
So for the operator ~, the goal was to have it behave like the & operator and call the constructor of the pointer wrapper class.
I don't think that is possible. It is certainly possible for user defined objects, but I don't think it is possible to overload unary operators for builtin types. So there are three solutions depending on what you prefer:
The first one does exactly what you want, but will break for primitive types:
#include <iostream>
template<typename T>
struct A {
T* payload;
A()
: payload(NULL){}
A(T *ptr)
: payload(ptr) {}
T& operator !(){
return *payload;
}
};
// this will not work for primary types
template<typename T>
A<T> operator ~(T &b){
return A<T>(&b);
}
struct B{
int test;
};
int main(){
B b; b.test = 4;
A<B> a;
a = ~b; // I think this is what you want
std::cerr << (!a).test << std::endl;
// this does not work
//int i = 4;
//A<int> a;
//a = ~i;
}
Second solution: use a compound assignment operator. Pros are the side effects are minimal, cons is this is not very intuitive and might break the nice design you had in mind.
#include <iostream>
template<typename T>
struct A {
T* payload;
A() : payload(NULL){}
T& operator !(){
return *payload;
}
};
template<typename T>
A<T>& operator &=(A<T> &a, T& b){ // should be friend of the above
a.payload = &b;
return a;
}
int main(){
int i = 3;
A<int> a;
a &= i;
std::cerr << !a << std::endl;
}
Third solution: overload the basic assignment operator. This is more intuitive to write but has a lot of side effects:
#include <iostream>
template<typename T>
struct A {
T* payload;
A() : payload(NULL){}
T& operator !(){
return *payload;
}
A<T>& operator = (T & b) {
payload = &b;
return *this;
}
};
int main(){
int i = 3;
A<int> a;
a = i;
std::cerr << !a << std::endl;
}
Someone might have a solution to hijack the operators for primitive types, but i can't think of any simple solution.
If i understood your code correctly, you want the operator ~ to return a copy of the pointer wrapper and the operator ! to act as dereference?
In this case, you can define the unary operator ~ inside the Apont class which calls a copy constructor. And the operator ! has to return a reference indeed if you want to asign a value.
I think the following c++ code defines what you want to do (I renamed Apont to A):
#include <iostream>
template<typename T>
struct A {
T* payload;
A(T *ptr)
:payload(ptr) {}
A(const A&other)
:payload(other.payload) {}
T& operator !(){
return *payload;
}
T* operator ~(){
return payload;
}
};
int main(){
#define PRINT(X) std::cerr << #X << " = " << X << std::endl
int i = 0;
PRINT(i);
A<int> a(&i);
!a = 1;
PRINT(i);
A<int> b = ~a;
!b = 2;
PRINT(i);
}
The output of the code above is:
i = 0
i = 1
i = 2
According to your comments, you said you wanted the operator ! to behave exactly like the wrapped pointer. You can do so, but then the syntax changes and you need to dereference it to assign a new value (because it is a pointer...). ie something like:
#include <iostream>
template<typename T>
struct A {
T* payload;
A(T *ptr): payload(ptr) {}
// this now behaves like accessing the wrapped pointer directly
T*& operator !(){
return payload;
}
};
int main(){
#define PRINT(X) std::cerr << #X << " = " << X << std::endl
int i = 0;
int j = 999;
PRINT(i);
A<int> a(&i);
*(!a) = 1; // note the change of syntax here
PRINT(*!a); // and here
!a = &j; // but now you can change the wrapped pointer through the operator
PRINT(*!a);
}