0

so I've made a class in c++ which has 2 reference type members:

class Edge{
private:
const Node& base;
const Node& target;

public:
    Edge(const Node& new1, const Node& new2);

I want to give default values to base and target in the C'tor. Which means that:

Edge()

will not be an error, but will do create an Edge object. How do I do that?

edit: I'm also trying to do:

Edge::Edge(const Node& newBase, const Node& newTarg)
{
    m_base=newBase;
    m_target=newTarg;
}

But it won't let me, it says no operator "=" matches this operators. But I did make a "=" operator for Nodes and checked it worked.......

Jjang
  • 243
  • 1
  • 6
  • 13
  • What have you tried? Do you know how to write default arguments for functions? – Kerrek SB Apr 30 '12 at 17:18
  • @KerrekSB: Adding default arguments doesn't really help. – Ben Voigt Apr 30 '12 at 17:20
  • This seems like a bad idea. What are you trying to do with reference member variables? – N_A Apr 30 '12 at 17:22
  • @BenVoigt - looks like it was the initaliser lists causing the issue, not the lifetime of the temporaries :) – Flexo Apr 30 '12 at 17:57
  • @awoodland: He just hadn't gotten that far yet ;) – Ben Voigt Apr 30 '12 at 18:02
  • You cannot assign references, and hence you cannot assign objects which *contain* references. It just doesn't make sense. Perhaps you want something like a `std::reference_wrapper`, which gives you a value-wrapper around a reference? – Kerrek SB Apr 30 '12 at 20:33

3 Answers3

5

You can give new1 and new2 defaults like any other parameter. The trick is that since they're passed by reference and (presumably) you're using them to set base and target they need to live long enough for this to make sense. You can do that by making a static "dummy" Node to use as the default for where one hasn't been specified, e.g.:

class Node {};

class Edge{
private:
static const Node none;
const Node& base;
const Node& target;

public:
    Edge(const Node& new1=none, const Node& new2=none) : base(new1), target(new2) {}
};

const Node Edge::none;

int main() {
  Edge e;
}

If that's good design or not is another issue though. There might well be a smarter solution to the underlying problem that you're trying to solve.

Flexo
  • 87,323
  • 22
  • 191
  • 272
  • i edited my question and added one thing: now my normal c'tor with values doesnt work too. – Jjang Apr 30 '12 at 17:53
  • @Jjang - that's a slightly different issue, there's a good answer at: http://stackoverflow.com/a/4589276/168175 - basically you need to use the initaliser list syntax like I did in my answer regardless of if you have a default or not. – Flexo Apr 30 '12 at 17:56
  • i got the point but i dont know what to do in my case. should i make 2 false nodes, just to initialize the const? – Jjang Apr 30 '12 at 18:01
  • @Jjang in the case you just added to your question you can do: `Edge::Edge(const Node& newBase, const Node& newTarg) : base(newBase), target(newTarget) {}` – Flexo Apr 30 '12 at 18:04
  • sure? my Node objects are getting int and not Node type. is that still good? – Jjang Apr 30 '12 at 18:17
  • p.s another error. "provides no intialization for:" i was trying to make a c'ctor.. >_> – Jjang Apr 30 '12 at 18:30
2

Here's a version that works for non-constant references, too:

struct Bar { /* ... */ }:

struct Foo
{
    Foo(Bar & br) : b(br)          { }
    Foo()         : b(default_bar) { }
private:
    static Bar default_bar;
    Bar & b;
};
Bar Foo::default_bar;

This way, all default-constructed Foo instances contain a reference to the common, static default_bar object.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
0

Another solution would be to use a wrapper that is copyable

struct Reference
    {
    T* r_noncopyable_object;
    };
user877329
  • 6,717
  • 8
  • 46
  • 88