views:

312

answers:

3

Solution:

This is an interesting problem, because sometimes we have no choice but to declare an explicitly qualified name.

std::string convert();

namespace tools {
  class Numeric {
    // ...
    // parsed as: "friend std::string::convert ();" 
    // (actual name is missing!). 
    friend std::string ::convert();
  };
}

In that case, prepending the name with :: is required, because otherwise we would declare and mark function tools::convert as friend (in the enclosing namespace). A solution to this problem is to wrap parentheses around the name:

friend std::string (::convert)();

Challenge:

I have this code that fails to compile. Can you figure out what's wrong? It caused headache to me once.

// header
namespace values {
  extern std::string address;
  extern int port;
}

// .cpp file
std::string  ::values::address = "192.0.0.1";
int          ::values::port    = 12;

It looks correct on the first sight. How many and which are the errors!?

+8  A: 

One error:

std::string values::address = "192.0.0.1"; 

is the proper form, otherwise the parse is

std::string::values::address = "192.0.0.1"; 

and there is no member "values" with a member "address" inside "string"...

it will work for builtin types, as they cannot ever contain members.. so int::values is an unambigous parse, int ::values, because the prior doesn't make sense.

std::string (::values::address) = "192.0.0.1"; 

works too. Note that if you typedef int sometype; that you'd have the same problem using sometype as you do with string above, but not with "int".

Jacob McIntosh
hah, you're the winner. Neat :)
Johannes Schaub - litb
fixed. as per litb's correction.
Jacob McIntosh
+2  A: 

I think it needs to be:

#include <string>

// header
namespace values {
  extern std::string address;
  extern int port;
}

// .cpp file
std::string  values::address = "192.0.0.1";
int          values::port    = 12;

I'm not sure that you can use the global scope resolution operator :: with namespaces ?

Paul R
agree ! Why would you do something like `int::port = 12` (assuming that the names are well resolved)
Ben
+2  A: 

I'm late to the game, but I would have preferred to write the .cpp file as:

// .cpp file
namespace values {
  std::string  address = "192.0.0.1";
  int          port    = 12;
}

Of course that doesn't solve the problem you had with the friend declaration.

Dan
I suspect my initial example with the "address" stuff was lame :) The friend example is much better. I agree with you that this way of definition is the better one :)
Johannes Schaub - litb