# Accessing the characters of a string literal at compile time?

## Recommended Posts

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?)

##### Share on other sites
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).

##### Share on other sites
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

##### Share on other sites
Ah, the limit must be 32-bits then. I just assumed you could extend it to 64. That sucks...

##### Share on other sites
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.

##### Share on other sites
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

##### Share on other sites
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.

##### Share on other sites
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.

##### Share on other sites
Hm, it appears my HTML got stripped. Here's the link in copy/paste form:

##### Share on other sites
Quote:
 Original post by _moagstar_  #define CRC3(STRING) CCompileTimeCRC3::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;    }

##### Share on other sites
Quote:
Original post by JohnBolton
Quote:
 Original post by _moagstar_  #define CRC3(STRING) CCompileTimeCRC3::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.

Keywords bolded. Your example is inconsequential, given that std::cout works just fine with runtime values.

Here's a working demonstration example of the problem:

template < char C > struct foo {};int main() {	foo< 'a'    > f1; //compiles fine	foo< "a"[0] > f2; //error C2975: 'C' : invalid template argument for 'foo', expected compile-time constant expression (MSVC 8.0, SP0)}

EDIT: Of course, the optimizer of any given compiler is probably smart enough for the compiler to determine the value of the expression at compile time, but sadly this alone is not enough to meet the C++ standard's requirements for a "compile-time constant expression".

[Edited by - MaulingMonkey on March 10, 2007 12:43:28 AM]

##### Share on other sites
Quote:
Original post by MaulingMonkey
Quote:
Original post by JohnBolton
Quote:
 Original post by _moagstar_  #define CRC3(STRING) CCompileTimeCRC3::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.

Keywords bolded. Your example is inconsequential, given that std::cout works just fine with runtime values.

Hmm. I should have tried it with this specific case. I guess "abc"[0] is too clever for the compiler, or that it doesn't consider it a constant expression because it stores "abc".

##### Share on other sites
Quote:
 Original post by JohnBoltonI guess "abc"[0] is too clever for the compiler
Wrong reasoning. The compiler may well be smart enough to figure it out as a compile-time constant, but it doesn't matter; The C++ standard mandates the behaviour, which is to fail independent of the compiler's cleverness.

##### Share on other sites
Quote:
Original post by Anonymous Poster
Quote:
 Original post by JohnBoltonI guess "abc"[0] is too clever for the compiler
Wrong reasoning. The compiler may well be smart enough to figure it out as a compile-time constant, but it doesn't matter; The C++ standard mandates the behaviour, which is to fail independent of the compiler's cleverness.

Again, bingo.

Example disassembly (MSVC8 SP0):
int main() {	std::cout << "a"[0] << "b"[0] << std::endl;00401000  mov         eax,dword ptr [__imp_std::endl (402038h)] 00401005  mov         ecx,dword ptr [__imp_std::cout (402054h)] 0040100B  push        eax  0040100C  push        62h  ; ASCII 'b'0040100E  push        61h  ; ASCII 'a'00401010  push        ecx  00401011  call        std::operator<<<std::char_traits<char> > (401160h) 00401016  add         esp,8 00401019  push        eax  0040101A  call        std::operator<<<std::char_traits<char> > (401160h) 0040101F  add         esp,8 00401022  mov         ecx,eax 00401024  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (402040h)] }

For those wondering why I've used two strings, it is because the optimizer seems to have spirited away my constant to places unknown the operator<< implementation with only one.

## Create an account or sign in to comment

You need to be a member in order to leave a comment

## Create an account

Sign up for a new account in our community. It's easy!

Register a new account

• ## Partner Spotlight

• ### Forum Statistics

• Total Topics
627654
• Total Posts
2978450

• 10
• 12
• 22
• 13
• 33