I wanted have implicit conversion in two level. The following code snippet is prototype of the problem I am facing.
//Sources
class A
{
public:
void print()
{
std::cout <<"Class A"<< std::endl;
}
operator int()
{
return 1;
}
};
class B
{
public:
void print()
{
std::cout <<"Class B"<< std::endl;
}
operator A()
{
return A();
}
};
class C
{
public:
void print()
{
std::cout <<"Class C"<< std::endl;
}
operator B()
{
return B();
}
};
void print_(A a)
{
a.print();
}
//driver
int main( int argc, char* argv[] )
{
C c;
//print_( c ); // compilation error
//print_( C() ); // compilation error
print_( c.operator framework::configuration::B() ); //when explicitly invoked it worked
return 0;
}
I looked into the example provided in the following links was convinced this is achievable.
How do conversion operators work in C++?
Operator overloading
The standard only allows one implicit conversion involving a user defined type. You have two, hence the compilation error.
See 12.3/4
At most one user-defined conversion (constructor or conversion function) is implicitly applied to a single
value.
Related
Extra line of code can be added only to the place where '>>' sign is present.
My targeted input and output is as follows:
Input: 15
Output : 16:15:17:16:
I need help only in
cout << r.get() << ":";
part. An explanation would be helpful.
#include <iostream>
using namespace std;
class A {
int i;
public:
A(int ai) : i(ai) {}
int get() const { return i; }
void update() { ++i; }
};
class B {
int i;
public:
B(int ai) : i(ai) {}
int get() const { return i; }
//>>
operator A() {return A(i);}
void update() { ++i; }
}; // End of class B
int main() {
int i;
cin >> i;
A a(i++);
B b(i);
const B &r = static_cast<B>(a);
a.update();
cout << a.get() << ":";
cout << r.get() << ":";
const A &s = static_cast<A>(b);
b.update();
cout << b.get() << ":";
cout << s.get() << ":";
return 0;
}
You cannot solve the asker's problem by modifying a conversion operator in class B. B's conversion operators only tell the constructor how to make another datatype out of a B. To do this with a conversion operator, the operator needs to be in class A.
class B; // forward declaration of B so that A knows it exists
class A
{
int i;
public:
A(int ai) :
i(ai)
{
}
int get() const
{
return i;
}
void update()
{
++i;
}
operator B(); // cannot implement the function yet because we do not have a
// complete definition of B. Without a definition of B we cannot
// construct B excluding forward defined helper functions that are
// implemented later, gaining us nothing.
};
Then later after B is fully defined,
A::operator B()
{
return B(i); // now we have enough information to construct a B
}
Note: We can reduce some of this messiness by moving the definition of B to before the definition of A. Unfortunately this makes the code required to support the
const A &s = static_cast<A>(b);
that comes later in the code require forward declaration of A and the implementation of the B to A conversion operator outside the definition of B.
An alternative is adding a constructor to B that takes an A
B::B(const A& a): i(a.get())
{
}
and vice-versa for A.
template<typename T>
class Pack
{
private:
std::function<T()> _Func = nullptr;
public:
Pack()
{
}
Pack(std::function<T()> func)
: _Func(func)
{
}
~Pack()
{
}
operator T()
{
return _Func();
}
};
What I use is operator T, I want to call _Func implicitly but I cannot even do it explicitly. It seems right but actually error C2440 #MSVC. I use it in two ways:
static member of class (succeeded);
member of class (failed)
(I don't know whether it matters or not)
I'm really wondering why it performs in two ways, and more importantly, how I can put it into my class as a non-static member and successfully call the operator T.
Member of the class:
struct test
{
test()
{
p_ = Pack<int>(std::bind(&test::foo, *this));
}
int foo()
{
std::cout << "test::foo" << std::endl;
return 5;
}
Pack<int> p_;
};
int main()
{
test t;
int x = t.p_;
return 0;
}
This works fine on VS 2013 EE.
I've hit a wall concerning this explicit copy constructor issue. I've been writing a class to figure things out:
#include <iostream>
template<class T>
class Mat
{
private:
T data;
public:
void set(T value)
{
data = value;
}
Mat()
: data(T(0))
{
}
explicit Mat(const Mat& another)
{
*this = another;
}
Mat& operator=(const Mat& another)
{
data = another.data;
return *this;
}
template<class U>
explicit operator Mat<U>()
{
Mat<U> result;
result.set(static_cast<U>(data));
return result;
}
void print()
{
std::cout << data << std::endl;
}
};
int main()
{
Mat< double > d1;
d1.set(3.14159);
Mat< int > i1(static_cast<Mat<int>>(d1));
d1.print();
i1.print();
std::cin.sync();
std::cin.ignore();
return 0;
}
I want my copy constructor to take only explicitly converted instances of another object, so I declared it explicit, but now I get the error error "C2558: class 'Mat' : no copy constructor available or copy constructor is declared 'explicit'", even though I made an explicit cast:
static_cast<Mat<int>>(d1)
I've declared the copy constructor explicit because I want this to be illegal:
Mat<float> a;
Mat<int> b(a);
While, I would like the following to remain legal:
Mat<float> a;
Mat<int> b(static_cast<Mat<int>>(a));
EDIT: I've been tinkering with this concepts trying to define exactly what I want to get, and I seem to get some funny results:
#include <iostream>
class MatB
{
private:
float data;
public:
MatB()
:data(0.0f)
{
}
void set(float value)
{
data = value;
}
float getData() const
{
return data;
}
void print()
{
std::cout << data << std::endl;
}
};
class MatA
{
private:
double data;
public:
MatA()
:data(0.0)
{
}
void set(double value)
{
data = value;
}
double getData() const
{
return data;
}
explicit operator MatB()
{
MatB temp;
temp.set(static_cast<float>(getData()));
return temp;
}
void print()
{
std::cout << data << std::endl;
}
};
class MatC
{
private:
int data;
public:
MatC()
:data(0)
{
}
explicit MatC(const MatB& in)
:data(static_cast<int>(in.getData()))
{
}
void print()
{
std::cout << data << std::endl;
}
};
int main()
{
MatA someA;
someA.set(3.14159);
MatC constructCFromA(someA);
someA.print();
constructCFromA.print();
std::cin.sync();
std::cin.ignore();
return 0;
}
In this example, constructCFromA(someA) shouldn't compile (imo) - even the linker marks it as an error(VS2013), still it compiles just fine... I am not sure whether my understanding of 'explicit' is incorrect, whether the IDE marks it as an error incorrectly, or the compiler compiles it even though it shouldn't. I thought I would need to do something like this:
constructCFromA(static_cast<MatB>(someA));
The IDE seems to agree with me, but the compiler doesn't. I must say I am pretty confused.
EDIT2:
Never mind, in Ideone it doesn't compile, so I guess MS are to blame.
I think the 2nd code illustrates well the behaviour I want to get. Basically make non-explicit conversions at initialization and assignment illegal. It seems however, that making the copy constructor explicit has various "side-effects".
The line where you did the explicit cast is not a problem. The problem that causes the compiling issue is on the line where you return Mat<U> by value:
template<class U>
explicit operator Mat<U>()
{
Mat<U> result;
result.set(static_cast<U>(data));
return result; // <<== This line requires a copy constructor to be defined
}
That is why when you remove explicit before the copy ctor, your code works just fine.
here's another version that will pass your unit test without the need for a conversion operator to T:
template<class T>
class Mat
{
private:
T data;
public:
void set(T value)
{
data = value;
}
// default constructor
Mat()
: data(T(0))
{
}
// construct from data type
explicit Mat(T dat)
: data(dat)
{}
// construct from any compatible Mat
template<class U>
explicit Mat(const Mat<U>& another)
: data(static_cast<T>(another.get_data()))
{}
// assign from any compatible Mat
template<class U>
Mat& operator=(const Mat<U>& another)
{
data = static_cast<T>(another.get_data());
return *this;
}
// provide a means to access data from unrelated Mat
const T& get_data() const { return data; }
void print()
{
std::cout << data << std::endl;
}
};
I have a question about equality comparison of lambdas.
I've tried to read some references but I've found nothing about this.
[] (Args ...args) -> ReturnType { ... };
For this type of lambdas, which are not closures actually because they have empty capture list, operators == and != works in the same way as for static functions (well, it seems, compiler generates them as static functions as well). But for closures any attempt to compare in the same way causes compilation error.
Here is simple programm for example:
#include <typeinfo>
#include <iostream>
struct WrapperBase {
virtual ~WrapperBase() = default;
virtual bool operator==(WrapperBase& v) = 0;
virtual bool operator!=(WrapperBase& v) = 0;
};
template<typename _Tp>
struct Wrapper : WrapperBase {
Wrapper(const _Tp& v) : value(v) { }
bool operator==(WrapperBase& v) override {
try {
Wrapper<_Tp>& vv = dynamic_cast<Wrapper<_Tp>&>(v);
return value == vv.value;
}
catch(std::bad_cast& err) { }
return false;
}
bool operator!=(WrapperBase& v) override {
try {
Wrapper<_Tp>& vv = dynamic_cast<Wrapper<_Tp>&>(v);
return value != vv.value;
}
catch(std::bad_cast& err) { }
return true;
}
//
_Tp value;
};
template<typename _Tp>
WrapperBase* create_wrapper(const _Tp& v) {
return new Wrapper<_Tp>(v);
}
struct Base {
Base(int a, int b) : wrapper(nullptr), a(a), b(b) { }
virtual ~Base() { delete wrapper; }
virtual WrapperBase* create_wrapper() = 0;
WrapperBase* wrapper;
int a;
int b;
};
struct ClassA : Base {
ClassA(int a, int b) : Base(a, b) {
wrapper = create_wrapper();
}
WrapperBase* create_wrapper() override {
auto lambda = [] (int v1, int v2) { return v1 + v2; };
return ::create_wrapper(lambda);
}
};
struct ClassB : Base {
ClassB(int a, int b) : Base(a, b) {
wrapper = create_wrapper();
}
WrapperBase* create_wrapper() override {
auto lambda = [=] (int v1, int v2) { return a + b + v1 + v2; };
return ::create_wrapper(lambda);
}
};
int main(int argc, char** argv) {
std::cout << std::boolalpha;
// all works fine:
ClassA a1(1, 2);
ClassA a2(3, 4);
std::cout << (*a1.wrapper == *a1.wrapper) << std::endl; // true
std::cout << (*a2.wrapper == *a2.wrapper) << std::endl; // true
std::cout << (*a1.wrapper == *a2.wrapper) << std::endl; // true
// cause compilation error:
ClassB b1(1, 2);
ClassB b2(3, 4);
std::cout << (*b1.wrapper == *b1.wrapper) << std::endl;
std::cout << (*b2.wrapper == *b2.wrapper) << std::endl;
std::cout << (*b1.wrapper == *b2.wrapper) << std::endl;
return 0;
}
Comparing lambdas created in instances of ClassA always return true even if they are created in different context (just as I said). On the other hand, ClassB do not even compile because operator == and != for its lambda is not found.
It seems, this programm is not well-formed, and comparing of lambdas in the way I've tried causes undefined behavior of the programm. But if it's really undefined behavior, how can they be compared? (I guess, nohow)
For this type of lambdas, which are not closures actually because they
have empty capture list, operators == and != works in the same way as
for static functions (well, it seems, compiler generates them as
static functions as well).
It works because the closure type of a lambda without captures provides a conversion operator that returns a function pointer. Those are comparable. [expr.prim.lambda]/6 (emphasis mine):
The closure type for a lambda-expression with no lambda-capture
has a public non-virtual non-explicit const conversion function to
pointer to function having the same parameter and return types as the
closure type’s function call operator. The value returned by this
conversion function shall be the address of a function that, when
invoked, has the same effect as invoking the closure type’s function
call operator.
(If the conversion operator was explicit the comparison would not work)
Roughly, a lambda of the form [] {} translates to
struct closure_type
{
private:
static void call() {}
public:
// closure_type() = delete; // Commented for the sake of the demo
closure_type& operator=(closure_type const&) = delete;
void operator()() const { /*return call();*/ }
operator decltype(&call)() const
{
return &call;
}
};
As you may have noted, the conversion operator returns the same function pointer each time. Though it would be utterly surprising if anything the like happened, the standard does allow different function pointers to be returned for a call to the conversion operator for the same closure object; A comparison of two closure objects has therefore an implementation-defined value. (It should, though, on all implementations be true for two closure objects of the same type.)
I have a sequence of types, which I want to be freely convertible to one another. Consider the following toy example:
struct A {
int value;
A(int v) : value(v) { }
};
struct B {
int value;
B(int v) : value(v) { }
B(A a) : value(a.value) { }
operator A() const { return A(value); }
};
struct C {
int value;
C(int v) : value(v) { }
C(A a) : value(a.value) { }
C(B b) : value(b.value) { }
operator B() const { return B(value); }
operator A() const { return A(B(*this)); } // <-- ambiguous
};
int main(int argc, const char** argv) {
C c(5);
A a(3);
a = c;
}
So as you see, I'm trying to defined each subsequent type to be convertible from all previous types using cast constructors, and to be convertible to all previous types using cast operators. Alas, this does not work as intended, as the definition of C::operator A is ambiguous according to gcc 4.7:
In member function ‘C::operator A() const’:
19:40: error: call of overloaded ‘B(const C&)’ is ambiguous
19:40: note: candidates are:
9:3: note: B::B(A)
6:8: note: constexpr B::B(const B&)
6:8: note: constexpr B::B(B&&)
Changing the expression to static_cast<A>(static_cast<B>(*this)) doesn't change a thing. Removing that line altogether results in an error message in main, as no implicit conversion sequence may use more than one user-defined conversion. In my toy example, I could perform the conversion from C to A direcly, but in my real life application, doing so would cause a lot of duplicate code, so I'd really like a solution which reuses the other conversion operators.
So how can I obtain a set of three freely interconvertible types without duplicating conversion code?
I'd try this way in struct C:
operator A() const { return this->operator B(); }
Try this:
operator A() const { return A(B(value)); }
or this:
operator A() const { return A(operator B()); }