tags:

views:

130

answers:

5

This is a bit weird, but here goes.

I have many hardcoded "tables" that I'm defining as arrays of std::strings or const char *.

So for example:

const char* resp_desc[] = {
    "00=Approved",
    "01=Declined",
    "03=Incorrect User name",
    // more values
    NULL
};

In some functions these are passed as the table to lookup the description:

const char* lookup(const char* code, const char** table, const char*default="") {
    // lookup code is here..
}

my question is, is it possible to call the lookup function without creating the resp_desc array?

The below code was my first attempt, but I get syntax errors around the {} when trying to use it:

const char* desc = lookup("00", {"00=Approved", "01-Invalid Record", NULL})
A: 

No sir! The curly bracket syntax is for array initialization only. It does not represent a literal array.

Imran
+2  A: 

In short, no. C++ doesn't provide array or structure literals, only array or structure initializers. That is, the { yadda, yadda, yadda } syntax only means what you want when it occurs on the right side of sometype name[] =.

hobbs
+1  A: 

The answer is no.

In C++ (and also C), array types in function parameters are automatically converted to pointer types, as your signature for lookup shows:

const char* lookup(const char* code, const char** table, const char *default);

table is a const char ** and so needs a pointer value. To have a pointer, you need an object in memory to point at.

If you had a simple function such as:

void myfunc(int foo);

you can call myfunc(1) and that's fine. The constant expression 1 is a temporary value which doesn't have a location in memory, and myfunc receives the value directly.

If however you call your lookup function:

const char* desc = lookup("00", /* array constant */);

we can ask: what could /* array constant */ possibly be? lookup needs a pointer to an array object which exists somewhere in memory; but a constant expression doesn't have a location in memory (it is not an lvalue or object) and so there can be no pointer which refers to the constant array expression. As a result, such constant expressions do not exist.

(The one exception to this rule of "no constants which decay to pointers" is the string literal: "Hello World". A string literal creates an array in memory with static duration which exists for the lifetime of the program, and its value returned is a const char * pointing to that array. Sadly, the equivalent for array literals does not exist.)

Philip Potter
+3  A: 

It doesn't work with the current C++03, but C++0x will allow to initialize i.e. std::vector with

std::vector<std::string>{"00=Approved", "01-Invalid Record"}

Edit: This works with g++ --std=c++0x (gcc --version is 4.4.3)

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

bool contains(string item, vector<string> const& table) {
  return find(table.begin(), table.end(), item) != table.end();
}

int main() {
  cout << (contains("foo", vector<string>{"foo", "bar"}) ? "found" : "not found") << "\n";
  return 0;
}
Maik Beckmann
Once you start using the c++0x features you can go for a map that reduces the cost of searching: `std::map<int,std::string> m{ {0,"Approved"}, {1, "Invalid Record} };` (or a map of `std::string`->`std::string` if the codes are really strings)
David Rodríguez - dribeas
+2  A: 

If you are willing to change your look-up function, you could alternatively use utilities like Boost.Assign:

// alternative lookup function:
std::string lookup(const std::string& code, 
                   const std::vector<std::string>& table, 
                   const std::string& default="");

// example:
const std::string desc = lookup("00", boost::assign::list_of
                                ("00=Approved")("01-Invalid Record"));

or maybe simply something like this:

typedef std::map<std::string,std::string> Table;
std::string lookup(const std::string& code, 
                   const Table& table, 
                   const std::string& default="")
{
    Table::iterator it = table.find(code);
    return (it != table.end()) ? it->second : default;
}

const std::string desc = lookup("00", boost::assign::map_list_of
                                ("00","Approved")("01","Invalid Record"));
Georg Fritzsche