Click here to Skip to main content
15,891,513 members
Please Sign up or sign in to vote.
2.00/5 (3 votes)
See more:
is there any way to qualify the members of an std::pair with something more meaningful that just first and second ?

for example :

std::pair<int, int> value;
value.first = something;
value.second = somethingelse;


I'd like to have
std::pair<int, int > value;
value.myfirstvalue = something;
value.mysecondvalue = somethingelse;



I know I could just define a simple struct
struct
{ 
   int myfirstvalue;
   int mysecondvalue;
};


but I'd have to make this struct visible to everyone who need to access it, std::pair is already visible to all.

Thanks.
Posted
Comments
Sergey Alexandrovich Kryukov 1-Jun-11 16:37pm    
Why?
--SA
Albert Holguin 1-Jun-11 22:00pm    
in this case, shouldn't your question be about achieving the same level of visibility of std::pair easily instead of replacing it... this is a trivial question btw... not sure why visibility is an issue... using a pre-compiled header? put a header there for your library of definitions.

There are several ways (some make poor sense), for instance you may use preprocessor macros or if you're concerned about, two methods (of course, in order to implement the methods you've to derive from the pair struct).
 
Share this answer
 
Comments
Stefan_Lang 6-Jun-11 3:49am    
My 4 for a feasible solution without bothering to warn of its dangers or at least propose how to minimize it. (Ok that's of course just an IMHO - I just don't like macros ;p But I'm aware many people out there, including some good programmers, harbor less scruples)
CPallini 6-Jun-11 4:05am    
Thanks.
I believe you have to pay a penalty for each 'non macro' approach.
Stefan_Lang 6-Jun-11 4:31am    
*shrug*
Noone's charged me yet.

I am of the opinion the only '#define' in a C++ program should be include guards. I hate it how windows headers clutter the global namespace with tons of #define symbols, and over the years I've wasted many weeks of hunting down inexplicable errors due to that fact alone. There is no excuse at all to worsen the mess even further (or create your own if you're not programming windows).

IMHO :)
CPallini 6-Jun-11 4:41am    
Maybe noone charged you, but your solution simply doubles the size of every pair. I wouldn't pay such a price.
Stefan_Lang 6-Jun-11 6:27am    
Ummm, no. References are not objects and thus don't take additional space. They're just aliases, an alternative way to access a memory location. The compiler will optimze them away the same way the preprocessor replaces a macro - in the resulting assembler code you wouldn't see a difference.

The big difference is that references are typesafe and don't clutter the global namespace. But that's it.
Could you use inheritence

class MyPair : private std::pair<int,> 
{
   public:
     void SetMyFirstValue(int value) { first=value; }
     void SetMySecondValue(int value) { second=value; }
     int GetMyFirstValue() { return first; }
     int GetMySecondValue() { return second; }
     
}


Then access as

MyPair value;
value.SetMyFirstValue(something);
value.SetMysecondValue(somethingelse);
 
Share this answer
 
v2
Comments
Stefan_Lang 6-Jun-11 3:37am    
Good solution, although it would have been somewhat closer to the OPs specification if you just defined two member functions:
int& MyFirstValue() { return first; }
int& MySecondValue() { return second; }

YOu'd apply these like this:

MyPair value;
value.MyFirstValue() = sth;
value.MySecondValue() = sth_else;

Just a matter of notation of course, but I always strive to come as close to the required specification as possible. ;-)
If you have a compound object containing this pair, you can add references to the two elements. References are not objects and as such don't take additional space. They only work as an alias, and that is what you apparently want:
class MyClass {
   std::pair<int,int> mypair;
   int& myfirstvalue;
   int& mysecondvalue;
public:
   MyClass() : myfirstvalue(mypair.first), mysecondvalue(mypair.second) {}
};

Note that you'll need to initialize these references in each constructor, so this can be kind of awkward.
 
Share this answer
 
v2
Comments
Maximilien 1-Jun-11 11:00am    
cute, but it is a bit over-kill.

Thanks.
Albert Holguin 1-Jun-11 21:57pm    
i'm sure the cute comment won't get you a lot of fans... IMHO
Stefan_Lang 6-Jun-11 3:29am    
Whatever you think of it, besides preprocessor macros, as C. Pallini suggested, this is the only way to achieve what you asked for.

Personally, I'd just stick with first and second, even though I agree it's somewhat unwieldy at times. But then, if the pair is embedded inside a class, only a few member functions should ever access it, so this use wouldn't be overly troublesome.

Anyway, you asked for a solution and I gave it. Youd didn't specify you'd have to like it. ;p
This should do it, keeping the original std::pair<int, int> functionality:
C++
struct MyPair : std::pair<int, int>
{
    typedef std::pair<int, int> Pair;
    int & something;
    int & somethingelse;
    MyPair() : something(Pair::first), somethingelse(Pair::second)
    {}
    MyPair(const Pair& pair) : Pair(pair), something(Pair::first), somethingelse(Pair::second)
    {}
    operator const Pair& () const
    {
        return *this;
    }
};

Use it like the underlying std::pair<int, int>:
C++
MyPair p1(std::make_pair(10, 20));
MyPair p2 = std::make_pair(-10, -20);
MyPair p3 = p2;
int val = p3.something + p1.something;
p2.somethingelse = 333;

cheers,
AR
 
Share this answer
 
Comments
Stefan_Lang 6-Jun-11 3:40am    
Good extension to my solution (see solution 1), but you've got the constructors wrong. Check out the initialization I posted above.

Besides, what is that symbol 'Pair' you were using?

P.S.: If not for the abovementioned points I'd vote 5 for a perfectly encapsuled solution.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900