Correct idiom for character string (not std :: string) constants in C ++

Some time ago I asked about std :: string constants the correct idiom for std :: string constants? .

What I removed was not to use std :: string constants, but to use char string constants. So what is the best idiom for this

#define FOO "foo"

const char * const FOO = "foo";

const char FOO[] = "foo";

Desired Features

  • get the length at compile time. 1 and 3, but not 2 (sizeof does not work on 2)
  • may be included in .h without the linker complaining. all (i think)
  • no multiple copies in .o in related output. depends on the compiler (Maybe)

So it seems that # 3 is better, but scott meyers says you need to use # 2 (effective C ++ item # 1)

summary of answers

  • use jolly complex boilerplate code
  • use # 3

. # 3;

, OKish; , ( , , gcc , )

+3
5

.

(1) (2), static . , (3).

(2) (3), extern, (1).

, , , , ...

const char FOO[] = "foo";, , static, . , extern.

0

, ,...

  • ,
  • .h , ,
  • .o, ,

... idiom,

template< class Dummy >
struct Foo_
{
    static char const s[];
};

template< class Dummy >
char const Foo_<Dummy>::s[] = "Blah blah";

typedef Foo_<void> Foo;    // Now you can refer to Foo:s


#include <iostream>
using namespace std;
int main()
{
    cout << sizeof( Foo::s ) << " bytes: \"" << Foo::s << "\"\n";
}

.

, , char/wchar_t-agnostic , , .

:
MSVC 7.1 10.0 sizeof. , g++ 4.4.1, Comeau Online 4.3.10.1, MSVC 7.1 MSVC 10.0.

#include <stddef.h>

typedef ptrdiff_t   Size;

// Substitute a more general countOf
template< Size n >
struct SizedBuf { char sizer[n]; };

template< class Type, Size n >
SizedBuf< n > countOf_( Type (&)[n] ) { return n; }

#define COUNT_OF( array ) sizeof( countOf_( array ).sizer )

#define DEF_STRING( name, value )                               \
    template< class >                                           \
    struct name##_constant_                                     \
    {                                                           \
        static char const str[];                                \
        static Size const length    = COUNT_OF( value ) - 1;    \
    };                                                          \
                                                                \
    template< class Type >                                      \
    char const name##_constant_< Type >::str[] = value;         \
                                                                \
    template< class Type >                                      \
    Size const name##_constant_< Type >::length;                \
                                                                \
    typedef name##_constant_<void>  name;


DEF_STRING( a, "Argh, MSVC!" )
DEF_STRING( b, "Blah blah" )
DEF_STRING( c, "Currently there no 'inline' for data in C++." )


#include <iostream>

template< char const* s >
void foo() { std::cout << "foo() says: " << s << std::endl; }

int main()
{
    using namespace std;

    int const x[a::length] = {};    // Showing off compile time constant.
    foo<a::str>();                  // Showing off external linkage.

    cout << a::length << " characters: \"" << a::str << "\"." << endl;
}

hth.,

+4

. , . -, # 2, , extern .h .cpp :

// .h
extern const char*const STR;

// .cpp
const  char*const STR = "abc";

, , . , ( #define s), , STR_LEN. , , ..._LEN .

0

, .
, .

, .h .cpp, . ( ), , .

. , , , ,

- , .

!

0

Alf:

#include <iostream>

#define string_constant(pName, pLiteral)                    \
        template <typename = void>                          \
        struct pName##_detail                               \
        {                                                   \
            static const char value[];                      \
        };                                                  \
                                                            \
        template <typename T>                               \
        const char pName##_detail<T>::value[] = pLiteral;   \
                                                            \
        typedef pName##_detail<> pName

string_constant(my_constant, "this is a literal");

int main()
{
    std::cout << my_constant::value << std::endl;
    std::cout << sizeof my_constant::value << std::endl;
}

codepad. , VS2010.:/

0

Source: https://habr.com/ru/post/1770823/


All Articles