If class A modifies its construction parameters, can I initialize const A's with const parameters?

时光毁灭记忆、已成空白 提交于 2019-12-12 03:44:20

问题


Suppose I have

class A final { 
    int& ir; 
public:
    A(int& x) : ir(x) { }
    void set(int y) { ir = y; } // non-const method!
    int get() const { return ir; }
};

and

const int i;

Obviously I can't have

 A a(i);

since that would breaks constness. But I also cannot have

 const A a(i);

despite the fact that this will not break constness de-facto. C++ doesn't support "const-only" ctors, e.g. in this case one which would take a const int&. Is there a way to get const A a wrapping a reference to i - other than

A a(const_cast<int &>(i))

?


回答1:


"Const" means that the object is constant during between the constructor end and destructor begin (during construction, you must be able to change the object). C++ doesn't have a "preparation constructor" of sorts that is preferred for const objects.

You can try this workaround by applying boost::variant. This is not completely type-safe at compile time, but detect errors at runtime by throwing an exception at least.

#include <boost/variant.hpp>
#include <iostream>

class R {
  boost::variant<int&, const int&> v;
public:
  R(int&v):v(v) { }
  R(const int&v):v(v) { }

  // works with both
  int get() const { 
     return boost::apply_visitor( 
        [](int x){return x;}, v); 
  }

  // only works for non-const A. If at construction, a const
  // int was passed, throws an error at runtime
  void set(int x) {
     boost::get<int&>(v) = x;
  }
};


int main() {
  int a = 0;
  const int b = a;
  R r1(a);
  R r2(b);
  const R r3(a);
  std::cout << r1.get() << r2.get() << r3.get();
  // r3.set(1); // compile error
  r1.set(1); // works
  r2.set(1); // runtime error
}



回答2:


C++ doesn't have a concept of fully constant classes, and compiler may not perform if reference int & is used only as const int &. So basically, you cant do it.




回答3:


It's weird but

class A final {
    union{
    int& ir;
    const int &cir;
    };
public:
    A(int& x) : ir(x) { }
    A(const int& x) : cir(x) { }
    void set(int y) { ir = y; } // non-const method!
    int get() const { return ir; }
};

int main(int argc, char *argv[])
{
    const int cv = 8;
    int v = 6;
    A a( cv );
    std::cout << a.get() << std::endl;
    a.set( v );
    std::cout << a.get() << std::endl;
    return 0; 
}

Also your set and get method opearates on values not references, so it's looks like you a doing something wrong




回答4:


This is not how I would write the code but it somehow works. If you construct a template class from the const variable, the set() function is defined also const and does not change the state. By constructing from non-const variable, the set function is able to change the state.

#include <iostream>
#include <string>
#include <type_traits>

template<typename T>
class A
{
    T &_i;
public:
    A(T &i) : _i(i) {}

   template <typename D = T,
             typename = std::enable_if_t<std::is_const<D>::value
                                        >
            >
    void set(T i) const { std::cout << "Do nothing on set" << std::endl; }

   template <typename D = T,
             typename = std::enable_if_t<!std::is_const<D>::value>
            >    
    void set(T i) { std::cout << "Do something on set" << std::endl; }
};

int main()
{
    {
        std::cout << "Construct from NON const variable" << std::endl;
        int b = 5;

        A<decltype(b)> a(b);   

        a.set(3);
    }

   {
        std::cout << "Construct from const variable" << std::endl;
        int const  b = 5;

        A<decltype(b)> a(b);      

        a.set(3);
    }
}

This prints:

Construct from NON const variable
Do something on set
Construct from const variable
Do nothing on set



回答5:


class A { 
    const int& ir; //  <<-- it's a const int. 
    /* ... */
public:
    A(int& x) : ir(x) { }
};


来源:https://stackoverflow.com/questions/36773397/if-class-a-modifies-its-construction-parameters-can-i-initialize-const-as-with

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!