Home > OS >  C How to overload the subscript operator and return a function
C How to overload the subscript operator and return a function

Time:12-31

This question is same as i post. but i not get a good answer and now i try to make it much clear. (i hope!!)

I have a list (vector) that will hold 'key/value' pairs. Example of key/value pair is "Pi = 3.14159" or "UserName = Bob". The 'Value's can be string, bool, int, float, or doubles. I need functions for each data type that i can add to the list, for example.

Foo f; f["Pi"].SetFloat(3.14159);          <--- Add float key/value
Foo f; float myFloat = f["Pi"].GetFloat(); <--- Get float value
          or
Foo f; f["UserName"].SetStr("Bob");        <-- Add string key/value
Foo f; const char * name = f["UserName"].GetStr(); < -- Get String.

I have much of the code now. BUT i do not know how to overload the subscript [].

Foo & operator[]( const char * pszKey ){
   *this->????
 }  

The Foo & operator[]( const char * pszKey) should let me find the Key and inside the function should let me add key/value or return a value. I do not know how to add key/value or return the value useing the subscript operator. I hope someone can write a small code to help me understand and help me with is question??

This is some of my code i have now.

const char * va( const char * fmt, ... ) { // va = "VarArgs"
  // Format a value into a string.
 }

void Foo::SetString( const char * Key, const char * ) { // Private
   // Add 'key' and 'value' to a vector as a pair.
 }

const char * Foo::GetString( const char * key ) {  // Private
   // Look up 'key' from the vector and return the 'value'.
 }

...

const char * Foo::GetStr( const * Key ) {
  ...
 }
void Foo::SetStr( const char * Key, const int Value ) {
   SetStr( Key, va("%i", Value ));
 }

float Foo::GetFloat( const char * Key ) {
   return (float) atof( GetStr( Key ));
 }
void Foo::SetFloat( const char * Key ) {
  ....
 }  

void Foo::SetInt( .... ) ;
const int * Foo::GetInt(...);

void Foo::SetBool( ... ); 
const bool Foo::GetBool(...);

CodePudding user response:

The subscript operator should return whatever variant type you are using to store the float, int, string, etc.

And that variant type (Foo, is it?) should have assignment and conversion operators:

struct my_variant_type
{
  ...

  operator int   () const { return GetInt(); }
  operator float () const { return GetFloat(); }
  operator string() const { return GetStr(); }
  etc

  my_variant_type & operator = ( int n ) { SetInt( n ); return *this; }
  my_variant_type & operator = ( float f ) { SetFloat( f ); return *this; }
  my_variant_type & operator = ( const std::string & s ) { SetStr( s ); return *this; }
  etc
};

Now you can say things like:

float pi = my_collection["pi"];
my_collection["name"] = "Harry Potter";

CodePudding user response:

I do not understand exactly why not just use std::map<std::string, std::variant<...>> and use operator= with variant constructor for assignment and std::get<> for getting value of proper type. Anyway, here's a wrapper around with requested interface that you proposed:

#include <variant>
#include <string>
#include <map>

struct Foo {
    using Value = std::variant<
        std::string,
        bool,
        int,
        float,
        double>;
    std::map<std::string, Value> data;

    struct YourInterface {
        Value& v;
        float GetFloat() {
            return std::get<float>(v);
        }
        void SetFloat(float f) {
            v = Value(f);
        }
        void SetStr(std::string n) {
            v = Value(n);
        }
        std::string GetStr() {
            return std::get<std::string>(v);
        }
        // etc.
    };
    YourInterface operator[](const char *pszKey) {
        return FooInterface(data[pszKey]);
    }
};

int main() {
    Foo f;
    f["UserName"].SetStr("Bob");
    float myFloat = f["Pi"].GetFloat();
    f["UserName"].SetStr("Bob");
    std::string name = f["UserName"].GetStr();
}
  •  Tags:  
  • c
  • Related