Accessing the characters of a string literal at compile time?

Started by
12 comments, last by MaulingMonkey 17 years, 1 month ago
Hi, I would like to know if there is any way that I can get access to the characters of a string literal at compile time for use as template parameters. I have written some template classes for generating CRC's at compile time from an input string, the problem is that you have to pass the string in like this


unsigned int crc = CCompileTimeCRC6<'s','t','r','i','n','g'>::value;



Which isnt the nicest way of specifying a string. I really want to be able to access the individual characters in a string literal, something like this :


#define CRC3(STRING) CCompileTimeCRC3<STRING[0], STRING[1], STRING[2]>::value

unsigned int crc = CRC3("abc");



etc. But unfortunately the compiler does not see these as compile time values. Does anyone have any ideas, is it possible in any way to specify a string literal like this and access the individual chars to pass as template arguments (or set as enum values, or array sizes?)
Advertisement
You can get around it for short strings by using something like this:
__int64 nString = 'foobar';
However, that limits you to 8 letters (64 bits).
That doesn't compile for me (VS2005), first of all I get this :

error C2015: too many characters in constant


So I change to :

const __int64 = (const __int64)"foobar";


And I get :

error C2971: a local variable cannot be used as a non-type argument


So I moved the variable to a global :

error C2970: an expression involving objects with internal linkage cannot be used as a non-type argument


So I externed it and I get this :

error C2975: invalid template argument, expected compile-time constant expression


grrrr... For crying out loud c++, all the information you need is there at compile time ;)

It was a good effort though, thanks for you're input. It's a shame you can't do something like :

CCompileTimeCRC6<const __int64("foobar")>::value
Ah, the limit must be 32-bits then. I just assumed you could extend it to 64. That sucks...
Yep that works

template <int string>class Test{public:	enum	{		value = string;	}};const int temp = 'test';int b = Test< temp >::value;


Although I think the 4 character limit might be a problem ;) Although it's probably easier to specify things in terms of four character groups than 1 character at a time, so it's a start.

Thanks, it's very frustrating because it's a string literal, it's there at compile time, does any one know why you can't access the individual characters? It seems bizzare to me.
Might it be that a (null-terminated) string is stored as the address of the first character? This makes accessing any other characters a (albeit small) calculation which is something that is done at runtime and not at compile time.

PS: it is just a totally wild guess; I'm not much into these things so I might just have said something stupid.
(hmz the storage pointer thing might not hold for literals...)

Greetz,

Illco
Actually I think you're right, the string literals are (depending on compiler settings) stored in read-only memory at runtime, so it kind of makes sense.

But it's a little frustrating that the data is all there and present at compile time, you just can't get to it. I guess it's something I'm going to have to live with.
Did you recently post the same question at c.l.c++.m? If not, there is a long (but interesting) thread posted there on the same subject.

Sorry about posting Anonymous. My password was reset but my screen name (mfawcett) was registered with a previous (and now unaccessible) e-mail address.
Hm, it appears my HTML got stripped. Here's the link in copy/paste form:

http://groups.google.com/group/comp.lang.c++.moderated/browse_frm/thread/5ff993d820cb3006/#
Quote:Original post by _moagstar_
    #define CRC3(STRING) CCompileTimeCRC3<STRING[0], STRING[1], STRING[2]>::value    unsigned int crc = CRC3("abc");
But unfortunately the compiler does not see these as compile time values.

Are you sure? This code compiles and runs for me on VS 2005.
    #include "stdafx.h"    #include <iostream>        int main(int argc, char* argv[])    {        std::cout << "hello world"[0];        std::cout << "hello world"[1];        std::cout << "hello world"[2];        std::cout << "hello world"[3];        std::cout << "hello world"[4];        std::cout << "hello world"[5];        std::cout << "hello world"[6];        std::cout << "hello world"[7];        std::cout << "hello world"[8];        std::cout << "hello world"[9];        std::cout << "hello world"[10];        std::cout << std::endl;        return 0;    } 


John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!

This topic is closed to new replies.

Advertisement