Using a constant from another file in a typedef.

Hi,
I have a header file where I store all the typedefs.
One of these typedefs uses a constant that I need to initialize in another .cpp. The code that I have tried is this:

1
2
3
4
// ConfigurationFile.hpp
  // more typedefs.
  extern const unsigned int number;
  typedef std::map<std::string,number> MyMap;


1
2
3
4
5
6
7
8
9
// Initializer.hpp

class Initializer{
private:
// more things
public:
// more things
  void Execute();
};


1
2
3
4
5
6
7
8
9
10
// Initializer.cpp

#include Initializer.hpp
#include ConfigurationFile.hpp

void Initializer::Execute() {
  // more things
  const unsigned int number( ReadNumberFromConfFile() );
  // more things
}


ReadNumberFromConfFile() reads the value from a configuration file that always exists.

This code doesn't compile. I get this error message:
1
2
3
error: ‘number’ is not a valid template argument for type ‘unsigned int’ because it is a non-constant expression

error: invalid type in declaration before ‘;’ token


So, is it possible to create a constant inside a method and pass it to the header file for the typedef?.

Thanks.
closed account (zb0S216C)
What value does ReadNumberFromConfFile() return?

Wazzak
Hi,
What value does ReadNumberFromConfFile() return?

It returns a integer. The configuration file has this format:
1
2
// variable name  // value
number                  7
closed account (zb0S216C)
In the type-definition of MyMap, you must specify a type for both template parameters. If you're using C++11, you can use decltype() to obtain the type of its operand. For instance:

 
typedef std::map<std::string, decltype(number)> MyMap;

Wazzak
Last edited on
I'm using the previous standard, C++98 I think.

If I use decltype():
typedef std::map<std::string, decltype(number)> MyMap;, I get this:

1
2
error: ‘number’ cannot appear in a constant-expression
error: a function call cannot appear in a constant-expression
Last edited on
closed account (zb0S216C)
Templates consist of template parameters. These parameters normally require a type given to them, such as int, and float. When you pass a variable to a template parameter list when it expects a type, the compiler will evaluate the argument, which will be a value, not a type. Therefore, the compiler will not be able to deduce the type from the resulting value. For instance:

1
2
3
4
5
6
7
template <typename T>
struct S { };

int const v_(0);

typedef S<int> T; // OK; #1
typedef S<v_> U; // Not OK; #2 

#1) This is OK, because the template parameter T of S is given an actual type.
#2) This is not OK, because v_ evaluates to zero, which is not a type, but a integral constant.

Wazzak
Last edited on
So is there no way to pass that constant to the typedef unless I use the new standard?
closed account (zb0S216C)
Your compiler needs to support C++11's decltype(), then it's all gravy.

Wazzak
Ok. I'm using now g++ -std=c++0x and get this complaint:

1
2
3
error: type/value mismatch at argument 2 in template parameter list fortemplate<class T, unsigned int k> struct MyMap’

error:   expected a constant of type ‘unsigned int’, got ‘const unsigned int


WTF?
closed account (zb0S216C)
Post the new type-def.

Wazzak
Yes!!

typedef std::map<std::string,decltype(number)> MyMap;

The other things are the same as in the previous code.
Last edited on
closed account (zb0S216C)
Done, then? Don't forget to mark the topic as solved :)

Wazzak
Nope! I'm getting the errors I said in my previous post!

1
2
3
error: type/value mismatch at argument 2 in template parameter list fortemplate<class T, unsigned int k> struct MyMap’

error:   expected a constant of type ‘unsigned int’, got ‘const unsigned int
closed account (zb0S216C)
This works for me:

1
2
unsigned int const x_(0u);
typedef std::map<int, decltype(x_)> T;

The only possible reasons as to why it's not working are:

1) You're not compiling with C++11
2) Your object files and headers are out-of-date

Wazzak
Last edited on
I'm compiling with -std=c++0x. -std=c++11 is not recognized.
As for the object files out of date, I have removed all of the .o from the directory.
closed account (zb0S216C)
OK, the only way I can see for myself is by seeing the actual code. Could you please use this website: http://pastebin.com/ and post the links to your code.

Wazzak
Hi,
I can't show you the code since it's from work, it's copyrighted. However, I'm having the same problem with this little example:

http://pastebin.com/z9Pt6nMk

1
2
3
error: type/value mismatch at argument 2 in template parameter list fortemplate<class T, int k> class TemplatedClass’

error:expected a constant of type ‘int’, got ‘const int


I'm compiling with: g++ -std=c++0x main.cpp

If I don't use decltype(), everything works.

PS: My version of g++ is 4.4.3 and the S.O. is Ubuntu 10.04.
Last edited on
closed account (zb0S216C)
TemplatedClass expects an integral value for its second template parameter, not a type, because the compiler knows its a constant integer type. Therefore, decltype() will not work because it yields a type, not a value. You have to pass it an integral value.

Wazzak
Last edited on
Topic archived. No new replies allowed.