-1

My Clion IDE shows me that there might be a problem while I am transferring a const double* type to a function which has a parameter const A when A defined with a double array as shown below.

When the second constructor of A is explicit there is a compilation error but when the second constructor of A is not explicit everything works fine. I assumed that there should be casting from const double* to const A but I am not sure. Then I debugged the code and I saw that only the first constructor of A was called.

So why does it matter if the second constructor is explicit of not?

class A {
public:
friend class B;
private:
    A(double v1, double v2): _x{v1, v2}{}
    explicit A(const double *arr2): _x{*arr2, *(arr2+1)}{}
    double _x[2];

};
class B {
private:
    A _b1, _b2;
    static double foo(const A &first, const A &second){
        return first._x[0]*second._x[1];
    }
public:
    B(): _b1(2.1, 2.2), _b2(1.2, 1.1){}
    B(double List[2][2]): _b1(List[0][0],List[0][1]), _b2(List[1][0], List[1][1]) 
  {}
    void Problem( const double* bArr, double* result) const{
        double goesTo=thisfunc();

        *result =foo(bArr, _b1)/goesTo; //this is where Clion states a possible problem
    }
    double thisfunc() const{

        return foo(_b1, _b2);
    }
};
int main() {
    double initArray[][2]={{2,1},{1,1}};
    B M(initArray);
    return 0;
} 
Christophe
  • 68,716
  • 7
  • 72
  • 138
  • I do not see any copy constructors in the shown code. – Sam Varshavchik Mar 02 '19 at 20:52
  • There is a copy constructor in B: static double foo(const A &first, const A &second). But you are right A doesnt have any copy constructor, and still while The second constructor of A is explicit there is an error – Valeri Grishin Mar 02 '19 at 20:58
  • That's not a copy constructor. The term "copy constructor" is a specific term in C++, with a very specific meaning. This is not a copy constructor. Neither of the two classes have a copy constructor. – Sam Varshavchik Mar 02 '19 at 20:59
  • My bad. You are right. But still i am getting an error in this code – Valeri Grishin Mar 02 '19 at 21:02
  • Please edit your question, then, and explain precisely what your question is. Talking about a "copy constructor" when there is no copy constructor anywhere, is confusing. – Sam Varshavchik Mar 02 '19 at 21:04
  • *this is where Clion states a possible problem* -- Please post the exact message, second, is this message really a compiler error? Third, CLion is not a compiler, it is an IDE. – PaulMcKenzie Mar 02 '19 at 21:07
  • I mentioned Clion and not the compiler because there is no message and only red mark. The compilation error is: no known conversion for argument 1 from 'const double*' to 'const A&' – Valeri Grishin Mar 02 '19 at 21:24
  • 2
    That's exactly what `explicit` does. – aschepler Mar 02 '19 at 21:36

2 Answers2

2

The code in the question is complicated, but the problem is simple.

void f(const A&);
double data[] = { 1.0, 2.0 };
f(data); // error

When A(const double*) is marked explicit the compiler is not allowed to use it to implicitly convert data into an object of type A. In order to use that constructor the code has to have an explicit conversion:

f(static_cast<A>(data));

After all, that’s what explicit means.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
1

It seems like you are passing the pointer bArr to a reference argument. You may want to dereference the pointer first:

*result =foo(*bArr, _b1)/goesTo;

Also I am 99% sure that is exactly what the error message states.

To answer your question. There is no implicit conversion(casting) from pointer to reference. You must explicitly use the dereference operator - prefixed*. Copy constructor is not a casting operator nor is casting operator a constructor.

Casting operator in class T converts from T to some other type. Copy constructor copies one instance of T to another instance of T. Ordinary constructor with one argument of some other type can be seen as converting said other type to an instance of type T.

EDIT: As pointed by Pete Becker this doesn't fix the problem as the explicit A(const double *arr2) is marked as explicit thus prohibiting the compiler doing the one implicit conversion that it's allowed to do. So correct solution is to directly create A from bArr or mark it as implicit

Quimby
  • 17,735
  • 4
  • 35
  • 55
  • No, this doesn’t fix the problem. The type of `*bArr` is `double`. `A` does not have a constructor that takes a single argument of type `double`. – Pete Becker Mar 02 '19 at 21:18
  • @PeteBecker You are right, I've read it wrongly. Thanks, I edited the answer – Quimby Mar 02 '19 at 21:23
  • First dereferencing the pointer still gives compilation error. Second why is this a problem to pass pointer to a reference parameter? – Valeri Grishin Mar 02 '19 at 21:27
  • "You must explicitly use the dereference operator - prefixed*". which mean is when i pass bArr i am passing the refference of the pointer? If so why this should be converted? (just trying to understand) – Valeri Grishin Mar 02 '19 at 21:45
  • @ValeriGrishin It is a problem because pointers and references are not the same. Pointers can be null, references not. Pointers can be redirected, that is part of the reason why you have to manually dereference it to get the value, because in some cases you also might need to access the pointer itself and if the pointer automatically converted itself to the value you wouldn't be able to. Just google more info. "i am passing the refference of the pointer". No you are passing a reference to the value the pointer points to. And see my edit for solution. – Quimby Mar 02 '19 at 22:08