Compile-time strlen
От: lifrsdn  
Дата: 29.11.07 11:19
Оценка:
Есть ли какой-нибудь класс, служащий оберткой для строковых литералов.

Что-нибудь в духе

std::string s="Hello";
f(s.c_str(),s.size());


Только в первой строке произойдет копирование в буфер. Хотелось бы этого по возможности избежать. А во второй избежать вызова strlen или совсем, или хотя бы многократного.

Если есть 2 класса, один из которых, скажем ограничивает интерфейс только константными методами, а второй копирует в буфер только по необходимости, то совсем замечательно было бы.
Re: Compile-time strlen
От: MShura  
Дата: 29.11.07 11:22
Оценка:
L>Есть ли какой-нибудь класс, служащий оберткой для строковых литералов.

L>Что-нибудь в духе


L>
L>std::string s="Hello";
L>f(s.c_str(),s.size());
L>


Тут std::string не нужен:

f("Hello",sizeof("Hello")-1);
Re: Compile-time strlen
От: Bell Россия  
Дата: 29.11.07 11:25
Оценка: 1 (1)
Здравствуйте, lifrsdn, Вы писали:

L>Есть ли какой-нибудь класс, служащий оберткой для строковых литералов.


L>Что-нибудь в духе


L>
L>std::string s="Hello";
L>f(s.c_str(),s.size());
L>


L>Только в первой строке произойдет копирование в буфер. Хотелось бы этого по возможности избежать. А во второй избежать вызова strlen или совсем, или хотя бы многократного.


L>Если есть 2 класса, один из которых, скажем ограничивает интерфейс только константными методами, а второй копирует в буфер только по необходимости, то совсем замечательно было бы.


void f (const char* ptr, int sz) {}

template<int N>
void f(const char (&arr)[N])
{
   return f(arr, N-1);
}


int main()
{
   f("Hello");
   return 0;
}
Любите книгу — источник знаний (с) М.Горький
Re[2]: Compile-time strlen
От: lifrsdn  
Дата: 29.11.07 11:43
Оценка:
Здравствуйте, MShura, Вы писали:

L>>Есть ли какой-нибудь класс, служащий оберткой для строковых литералов.


L>>Что-нибудь в духе


L>>
L>>std::string s="Hello";
L>>f(s.c_str(),s.size());
L>>


MS>Тут std::string не нужен:


MS>
MS>f("Hello",sizeof("Hello")-1);
MS>


Хм, как насчет того, что дублируются строки? А если они длинные?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: Compile-time strlen
От: lifrsdn  
Дата: 29.11.07 11:43
Оценка:
Здравствуйте, Bell, Вы писали:

...

B>
B>void f (const char* ptr, int sz) {}

B>template<int N>
B>void f(const char (&arr)[N])
B>{
B>   return f(arr, N-1);
B>}


B>int main()
B>{
B>   f("Hello");
B>   return 0;
B>}
B>


Так это к каждой функции нужно писать обертку. Хотя явно лучше варианта MShura. А всё таки легковесного класса нет?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Compile-time strlen
От: Conr Россия  
Дата: 29.11.07 11:49
Оценка:
Здравствуйте, lifrsdn, Вы писали:

B>>
B>>void f (const char* ptr, int sz) {}

B>>template<int N>
B>>void f(const char (&arr)[N])
B>>{
B>>   return f(arr, N-1);
B>>}


B>>int main()
B>>{
B>>   f("Hello");
B>>   return 0;
B>>}
B>>


L>Так это к каждой функции нужно писать обертку. Хотя явно лучше варианта MShura. А всё таки легковесного класса нет?

как вариант:

template<typename T, int len>
int str_len_ct(const T (&)[len])
{
   return len-1;
}

int main(int argc, const char * argv[])
{
   int len = str_len_ct("Hello");
   int len2 = str_len_ct(L"unicode");
}
Re[4]: Compile-time strlen
От: Conr Россия  
Дата: 29.11.07 11:57
Оценка:
Здравствуйте, Conr, Вы писали:

Тьфу, не то запостил:

void f (const char* ptr, int sz) {}
void f (const wchar_t* ptr, int sz) {}

static const char str1[] = "Hello";
static const wchar_t str2[] = L"Unicode";

template<typename T, int len>
int str_len_ct(const T (&)[len])
{
   return len-1;
}

int main(int argc, const char * argv[])
{
    f(str1,str_len_ct(str1));
    f(str2,str_len_ct(str2));
}
Re[4]: Compile-time strlen
От: lifrsdn  
Дата: 29.11.07 12:00
Оценка:
Здравствуйте, Conr, Вы писали:

...

L>>Так это к каждой функции нужно писать обертку. Хотя явно лучше варианта MShura. А всё таки легковесного класса нет?

C>как вариант:

C>template<typename T, int len>
C>int str_len_ct(const T (&)[len])
C>{
C>   return len-1;
C>}

C>int main(int argc, const char * argv[])
C>{
C>   int len = str_len_ct("Hello");
C>   int len2 = str_len_ct(L"unicode");
C>}


А чего-нибудь похожего на

template<typename T, int len>
class StringLiteral
{
...
public:
    StringLiteral(const T (&b)[l])
    {
        buf=b;
        len=l;
    }
    size_t size()
    {
        return len;
    }
    const T* c_str()
    {
        return buf;
    }
}


И более-менее стандартного при этом нет?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Compile-time strlen
От: Erop Россия  
Дата: 29.11.07 12:01
Оценка:
Здравствуйте, lifrsdn, Вы писали:

L>
L>std::string s="Hello";
L>f(s.c_str(),s.size());
L>


Ну напиши
Скажем так как-то:

class constStr {
public:
    template<int N>
    constStr( const char (&str)[N] ) : ptr( str ), count( N ) {}

    operator const char*() const { return ptr; };
    int size() const { return count; }

    // тут добавь интерфейса по вкусу...
private:
    char const * const ptr;
    const int count;
};
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Compile-time strlen
От: lifrsdn  
Дата: 29.11.07 12:04
Оценка:
Здравствуйте, Conr, Вы писали:

C>static const char str1[] = "Hello";

C>static const wchar_t str2[] = L"Unicode";

А вот в этом месте копирования при инициализации не будет? VS, вроде, скопирует из той области, где лежит Hello, например, в str1.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: Compile-time strlen
От: lifrsdn  
Дата: 29.11.07 12:07
Оценка:
Здравствуйте, Erop, Вы писали:

...

E>Ну напиши

E>Скажем так как-то:

E>
class constStr {
E>public:
E>    template<int N>
E>    constStr( const char (&str)[N] ) : ptr( str ), count( N ) {}

E>    operator const char*() const { return ptr; };
E>    int size() const { return count; }

E>    // тут добавь интерфейса по вкусу...
E>private:
E>    char const * const ptr;
E>    const int count;
E>};


Re[4]: Compile-time strlen
Автор: lifrsdn
Дата: 29.11.07
Написать-то можно, но как известно, всё украдено до нас. Может кто уже сделал такое.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Compile-time strlen
От: np9mi7 Россия  
Дата: 29.11.07 12:08
Оценка:
Здравствуйте, lifrsdn, Вы писали:

L>Только в первой строке произойдет копирование в буфер. Хотелось бы этого по возможности избежать. А во второй избежать вызова strlen или совсем, или хотя бы многократного.


L>Если есть 2 класса, один из которых, скажем ограничивает интерфейс только константными методами, а второй копирует в буфер только по необходимости, то совсем замечательно было бы.


Может имеет смысл посмотреть в сторону const_string ?
[RSDN@Home 1.2.0 alpha rev. 775 on Windows XP 5.1.2600.131072]
"В любое мгновение принятия решения, лучшее, что вы можете сделать, это принять правильное решение; следующим лучшим вариантом будет принять неправильное решение, худший вариант – не принимать решения совсем" (c) Теодор Рузвельт.
Re[3]: Compile-time strlen
От: MShura  
Дата: 29.11.07 12:24
Оценка: -1
MS>>Тут std::string не нужен:

MS>>
MS>>f("Hello",sizeof("Hello")-1);
MS>>


L>Хм, как насчет того, что дублируются строки? А если они длинные?


#define STR_HELLO "Hello"
или
static const char STR_HELLO[] = "Hello";

f( STR_HELLO, sizeof(STR_HELLO)-1 );
Re[5]: Compile-time strlen
От: Conr Россия  
Дата: 29.11.07 12:34
Оценка:
Здравствуйте, lifrsdn, Вы писали:

L>А чего-нибудь похожего на


L>
L>template<typename T, int len>
L>class StringLiteral
L>{
L>...
L>public:
L>    StringLiteral(const T (&b)[l])
L>    {
L>        buf=b;
L>        len=l;
L>    }
L>    size_t size()
L>    {
L>        return len;
L>    }
L>    const T* c_str()
L>    {
L>        return buf;
L>    }
L>}
L>


L>И более-менее стандартного при этом нет?

Имхо нет, да и работать это будет только со статически константными строками, определенными в этом же модуле.
Re[2]: Compile-time strlen
От: Аноним  
Дата: 29.11.07 12:52
Оценка:
Здравствуйте, Bell, Вы писали:


B>
B>void f (const char* ptr, int sz) {}

B>template<int N>
B>void f(const char (&arr)[N])
B>{
B>   return f(arr, N-1);
B>}

B>


Вопрос почти по теме.
Почему такой код работает:
template<typename T, size_t t_n>
inline size_t arr_size(const T (&)[t_n]){
    return t_n;
}


А такой не работает:
template<typename T, size_t t_n>
inline size_t arr_size(const T [t_n]){
    return t_n;
}
.........
.........
int  arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
cout << arr_size(arr) << endl;
.........


error C2784: 'size_t arr_size(const T [t_n])' : could not deduce template argument for 'const T [t_n]' from 'int [12]'
(VS2005)

?
Re[6]: Compile-time strlen
От: lifrsdn  
Дата: 29.11.07 13:04
Оценка:
Здравствуйте, Conr, Вы писали:

...

C>Имхо нет, да и работать это будет только со статически константными строками, определенными в этом же модуле.


Так больше ничего и не надо. Просто думал, что может уже есть что-то похожее.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: Compile-time strlen
От: Erop Россия  
Дата: 29.11.07 15:20
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Bell, Вы писали:

А>error C2784: 'size_t arr_size(const T [t_n])' : could not deduce template argument for 'const T [t_n]' from 'int [12]'
А>(VS2005)

А>?


Потому, что f( T t[] ), f( T t[12] ) и f( T* const t ) эквивалентны. Так что вывести длину массива действительно никак не получится.

Хинт: как передавать массив по значению собираешься?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Compile-time strlen
От: Аноним  
Дата: 29.11.07 19:49
Оценка:
Здравствуйте, Erop, Вы писали:

E>Потому, что f( T t[] ), f( T t[12] ) и f( T* const t ) эквивалентны. Так что вывести длину массива действительно никак не получится.

E>Хинт: как передавать массив по значению собираешься?
Во блин. Прикольный язык, ИМХО его невозможно выучить до конца — пока выучишь, новый стандарт приймут
Я знал, что f( T t[] ) эквивалентно f( T* const t ),
но как-то не подумал что f( T t[X] ) == f( T t[Y] ) == f( T t[] ) == f( T* const t ).
Спасибо.
Re: Compile-time strlen
От: _nn_  
Дата: 29.11.07 20:39
Оценка:
Здравствуйте, lifrsdn, Вы писали:

L>Есть ли какой-нибудь класс, служащий оберткой для строковых литералов.


L>Что-нибудь в духе


L>
L>std::string s="Hello";
L>f(s.c_str(),s.size());
L>


Поиск по форуму ?
http://www.rsdn.ru/forum/message/2295069.1.aspx
Автор: igna
Дата: 10.01.07

http://www.rsdn.ru/forum/message/2186167.1.aspx
Автор:
Дата: 27.10.06


L>Только в первой строке произойдет копирование в буфер. Хотелось бы этого по возможности избежать. А во второй избежать вызова strlen или совсем, или хотя бы многократного.


L>Если есть 2 класса, один из которых, скажем ограничивает интерфейс только константными методами, а второй копирует в буфер только по необходимости, то совсем замечательно было бы.


Насчет копирование решается просто: Boost.Range (Поиск по форуму помогает )

typedef boost::iterator_range<char> char_range;

void f(char_range p)
{
}

std::string my_str("aa"); // Copy
f(make_iterator_range(my_str));

char const my_array[] = "aa";
f(make_iterator_range(my_array)); // No copy
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[2]: Compile-time strlen
От: lifrsdn  
Дата: 29.11.07 21:03
Оценка:
Здравствуйте, _nn_, Вы писали:

__>Насчет копирование решается просто: Boost.Range (Поиск по форуму помогает )


__>
__>typedef boost::iterator_range<char> char_range;

__>void f(char_range p)
__>{
__>}

__>std::string my_str("aa"); // Copy
__>f(make_iterator_range(my_str));

__>char const my_array[] = "aa";  //Copy
__>f(make_iterator_range(my_array)); // No copy
__>
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.