Re: Функции для массивов и указателей
От: Constructor  
Дата: 24.11.15 19:16
Оценка: 3 (1) +1
Здравствуйте, Tasheehoo, Вы писали:

T>Пытаюсь сделать такое:

T>
T>const char s0[] = "123";
T>const char *s1 = "456";
T>func(s0);
T>func("789");
T>func(s1);
T>

T>Т.е. нужна перегрузка функции func() для указателей и массивов char`ов. Что-то ничего не получается... Подскажите, плиз.

Как-то так:

#include <iostream>
#include <type_traits>

template <typename ConstCharPointer>
std::enable_if_t<std::is_same<ConstCharPointer, const char*>::value> func(ConstCharPointer)
{
    std::cout << "'func' overload for pointers" << std::endl;
}

template <size_t ArraySize>
void func(const char(&)[ArraySize])
{
    std::cout << "'func' overload for arrays" << std::endl;
}

int main()
{
    const char s0[] = "123";
    const char *s1 = "456";
    
    func(s0);
    func("789");
    func(s1);
}
Re[2]: Функции для массивов и указателей
От: _hum_ Беларусь  
Дата: 25.11.15 08:40
Оценка: +1 -1
Здравствуйте, Constructor, Вы писали:

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


T>>Пытаюсь сделать такое:

T>>
T>>const char s0[] = "123";
T>>const char *s1 = "456";
T>>func(s0);
T>>func("789");
T>>func(s1);
T>>

T>>Т.е. нужна перегрузка функции func() для указателей и массивов char`ов. Что-то ничего не получается... Подскажите, плиз.

C>Как-то так:


C>
C>#include <iostream>
C>#include <type_traits>

C>template <typename ConstCharPointer>
C>std::enable_if_t<std::is_same<ConstCharPointer, const char*>::value> func(ConstCharPointer)
C>{
C>    std::cout << "'func' overload for pointers" << std::endl;
C>}

C>template <size_t ArraySize>
C>void func(const char(&)[ArraySize])
C>{
C>    std::cout << "'func' overload for arrays" << std::endl;
C>}

C>int main()
C>{
C>    const char s0[] = "123";
C>    const char *s1 = "456";
    
C>    func(s0);
C>    func("789");
C>    func(s1);
C>}
C>


а что обычный подход через
//--------------------------------
void func(const char* p)
{
    std::cout<<p<<std::endl;
}
//--------------------------------
int main()
{
    const char s0[] = "123";
    const char *s1 = "456";
    
    func(s0);
    func("789");
    func(s1);


    return 0;
}

уже устарел?
Re[2]: Функции для массивов и указателей
От: johny5 Новая Зеландия
Дата: 25.11.15 20:26
Оценка: +1
Здравствуйте, yatagarasu, Вы писали:

Y>Всегда интересовало зачем это нужно. Вопрос тут похоже каждый месяц всплывает )


К примеру, из массива можно вытащить его длину, этим мы экономим на strlen операции. С указателем размер строки утерян.
Функции для массивов и указателей
От: Tasheehoo  
Дата: 24.11.15 18:22
Оценка:
Пытаюсь сделать такое:
const char s0[] = "123";
const char *s1 = "456";
func(s0);
func("789");
func(s1);

Т.е. нужна перегрузка функции func() для указателей и массивов char`ов. Что-то ничего не получается... Подскажите, плиз.

Спасибо.
Re: Функции для массивов и указателей
От: Alexander G Украина  
Дата: 24.11.15 19:12
Оценка:
Здравствуйте, Tasheehoo, Вы писали:

T>Пытаюсь сделать такое:

T>
T>const char s0[] = "123";
T>const char *s1 = "456";
T>func(s0);
T>func("789");
T>func(s1);
T>

T>Т.е. нужна перегрузка функции func() для указателей и массивов char`ов. Что-то ничего не получается... Подскажите, плиз.


Ссылка на массив
void func(const char (&s)[4]);

template<size_t N>
void func(const char (&s)[N]);
Русский военный корабль идёт ко дну!
Отредактировано 24.11.2015 19:15 Alexander G . Предыдущая версия .
Re[2]: Функции для массивов и указателей
От: Tasheehoo  
Дата: 24.11.15 19:17
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>
AG>void func(const char (&s)[4]);

AG>template<size_t N>
AG>void func(const char (&s)[N]);
AG>

А где же перегрузка для указателей?
Re[2]: Функции для массивов и указателей
От: Tasheehoo  
Дата: 24.11.15 19:21
Оценка:
Здравствуйте, Constructor, Вы писали:

Спасибо, оно работает!
Re[3]: Функции для массивов и указателей
От: Constructor  
Дата: 25.11.15 12:08
Оценка:
Здравствуйте, _hum_, Вы писали:

__>а что обычный подход через

__>
__>//--------------------------------
__>void func(const char* p)
__>{
__>    std::cout<<p<<std::endl;
__>}
__>//--------------------------------
__>int main()
__>{
__>    const char s0[] = "123";
__>    const char *s1 = "456";
    
__>    func(s0);
__>    func("789");
__>    func(s1);


__>    return 0;
__>}
__>

__>уже устарел?

Если имелась в виду задача о написании перегрузок функции func для массивов char и указателей на char, то он никогда и не работал. Ваш код принимает и то, и то, не различая, что же он принял.
Re: Функции для массивов и указателей
От: yatagarasu Беларусь  
Дата: 25.11.15 13:41
Оценка:
Всегда интересовало зачем это нужно. Вопрос тут похоже каждый месяц всплывает )
Re[4]: Функции для массивов и указателей
От: _hum_ Беларусь  
Дата: 25.11.15 23:05
Оценка:
Здравствуйте, Constructor, Вы писали:

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


__>>а что обычный подход через

__>>
__>>//--------------------------------
__>>void func(const char* p)
__>>{
__>>    std::cout<<p<<std::endl;
__>>}
__>>//--------------------------------
__>>int main()
__>>{
__>>    const char s0[] = "123";
__>>    const char *s1 = "456";
    
__>>    func(s0);
__>>    func("789");
__>>    func(s1);


__>>    return 0;
__>>}
__>>

__>>уже устарел?

C>Если имелась в виду задача о написании перегрузок функции func для массивов char и указателей на char, то он никогда и не работал. Ваш код принимает и то, и то, не различая, что же он принял.


ааа, а мне почему-то показалось, что "перегрузка" звучала как "чего-нибудь типа перегрузки, чтоб токо работало".

п.с. раньше почему-то считал, что массив в с++ отождествляется с указателем на первый элемент массива. ан, оказывается (как следует из ваших примеров), — нет.
Re[2]: Функции для массивов и указателей
От: XuMuK Россия  
Дата: 26.11.15 08:22
Оценка:
Здравствуйте, yatagarasu, Вы писали:

Y>Всегда интересовало зачем это нужно. Вопрос тут похоже каждый месяц всплывает )


например, в массив можно положить несколько строк, разделенных \0.
Re[5]: Функции для массивов и указателей
От: alexolut  
Дата: 26.11.15 08:26
Оценка:
Здравствуйте, _hum_, Вы писали:

__>п.с. раньше почему-то считал, что массив в с++ отождествляется с указателем на первый элемент массива. ан, оказывается (как следует из ваших примеров), — нет.


Он не отождествляется, просто присутствует неявное преобразование массива в указатель:

4.2/1
An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue
of type “pointer to T”. The result is a pointer to the first element of the array.

Re[3]: Функции для массивов и указателей
От: Mr.Delphist  
Дата: 26.11.15 11:21
Оценка:
Здравствуйте, XuMuK, Вы писали:

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


Y>>Всегда интересовало зачем это нужно. Вопрос тут похоже каждый месяц всплывает )


XMK>например, в массив можно положить несколько строк, разделенных \0.


В принципе, ничто не мешает интерпретировать (char *p) как (void *p), а конец данных помечать маркером, оговоренным контрактом. Например, нули разеляют строки, двойной ноль означает "всё, конец" (как двойной перенос строки в HTTP-заголовках)
Re[6]: Функции для массивов и указателей
От: _hum_ Беларусь  
Дата: 26.11.15 11:36
Оценка:
Здравствуйте, alexolut, Вы писали:

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


__>>п.с. раньше почему-то считал, что массив в с++ отождествляется с указателем на первый элемент массива. ан, оказывается (как следует из ваших примеров), — нет.


A>Он не отождествляется, просто присутствует неявное преобразование массива в указатель:


A>

4.2/1
A>An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue
A>of type “pointer to T”. The result is a pointer to the first element of the array.


возможно. просто логика немного странноватая. ведь основной операцией для массива является разындексация, а для нее

The expression E1[E2] is identical (by definition) to *((E1)+(E2))

то есть, она по определению есть ни что иное, как разыменование указателя. потому, если считать что семантика выражения arr[i] включает в себя неявное приведения типа массива к указателю, то получается, что массив не имеет ни одной своей собственной операции (а работатть с ним можно только после преобразования к указателю. что довольно странно для нетривиального типа).
Re[7]: Функции для массивов и указателей
От: alexolut  
Дата: 26.11.15 12:00
Оценка:
Здравствуйте, _hum_, Вы писали:

__>возможно. просто логика немного странноватая. ведь основной операцией для массива является разындексация, а для нее

__>

__>The expression E1[E2] is identical (by definition) to *((E1)+(E2))

__>то есть, она по определению есть ни что иное, как разыменование указателя. потому, если считать что семантика выражения arr[i] включает в себя неявное приведения типа массива к указателю, то получается, что массив не имеет ни одной своей собственной операции (а работатть с ним можно только после преобразования к указателю. что довольно странно для нетривиального типа).

Выражение *((E1)+(E2)) справедливо как для массивов, так и для указателей. Из того же параграфа:

One of the expressions shall have the type “array of T” or “pointer to T” and the other shall have unscoped enumeration
or integral type.

Насчет особенных операций, например, sizeof от массива вернет размер массива (т.е. никакого неявного преобразования в указатель не будет).
Re[8]: Функции для массивов и указателей
От: _hum_ Беларусь  
Дата: 26.11.15 12:32
Оценка:
Здравствуйте, alexolut, Вы писали:

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


__>>возможно. просто логика немного странноватая. ведь основной операцией для массива является разындексация, а для нее

__>>

__>>The expression E1[E2] is identical (by definition) to *((E1)+(E2))

__>>то есть, она по определению есть ни что иное, как разыменование указателя. потому, если считать что семантика выражения arr[i] включает в себя неявное приведения типа массива к указателю, то получается, что массив не имеет ни одной своей собственной операции (а работатть с ним можно только после преобразования к указателю. что довольно странно для нетривиального типа).

A>Выражение *((E1)+(E2)) справедливо как для массивов, так и для указателей. Из того же параграфа:

A>

A>One of the expressions shall have the type “array of T” or “pointer to T” and the other shall have unscoped enumeration
A>or integral type.

а кто говорил, что выражение несправеливо? я лишь вел к тому, что если считать оператор разыменования "звездочка" оператором, действующим только на значениях типа "указатели", то массив автоматом должен преобразовываться в этот тип в указанном выражении. ну, или второй вариант — считать, что есть два разных оператора "звездочка" — один действует на массивах, другой на указателях.


A>Насчет особенных операций, например, sizeof от массива вернет размер массива (т.е. никакого неявного преобразования в указатель не будет).


это не операция типа в исходном смысле (операция, определяющая допустимые действия над значениями, входящими в данный тип). массив и без нее останется массивом (а вот без операции разындексации массив как общепринятый тип данных исчезнет).
Re[9]: Функции для массивов и указателей
От: alexolut  
Дата: 26.11.15 13:55
Оценка:
Здравствуйте, _hum_, Вы писали:

__>я лишь вел к тому, что если считать оператор разыменования "звездочка" оператором, действующим только на значениях типа "указатели", то массив автоматом должен преобразовываться в этот тип в указанном выражении. ну, или второй вариант — считать, что есть два разных оператора "звездочка" — один действует на массивах, другой на указателях.

Оператор один единственный, в выражении *((E1)+(E2)) происходит неявное преобразование имени массива в указатель.

A>>Насчет особенных операций, например, sizeof от массива вернет размер массива (т.е. никакого неявного преобразования в указатель не будет).

__>это не операция типа в исходном смысле (операция, определяющая допустимые действия над значениями, входящими в данный тип). массив и без нее останется массивом (а вот без операции разындексации массив как общепринятый тип данных исчезнет).
Понятно, что если мы будем считать массивом только то, для чего можно выполнить разындексацию, то без разындексации это перестанет быть массивом в нашем понимании.
Но массив в первую очередь это непрерывная последовательность однотипных данных, а уж как обращаться к этим элементам, через [] или *+ дело десятое.
Re[10]: Функции для массивов и указателей
От: _hum_ Беларусь  
Дата: 26.11.15 14:09
Оценка:
Здравствуйте, alexolut, Вы писали:

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


__>>я лишь вел к тому, что если считать оператор разыменования "звездочка" оператором, действующим только на значениях типа "указатели", то массив автоматом должен преобразовываться в этот тип в указанном выражении. ну, или второй вариант — считать, что есть два разных оператора "звездочка" — один действует на массивах, другой на указателях.

A>Оператор один единственный, в выражении *((E1)+(E2)) происходит неявное преобразование имени массива в указатель.

то есть, я так понял, вы согласны с тем, что, де-юре, у типа "массив" нет своей собственной операции разындексации

A>>>Насчет особенных операций, например, sizeof от массива вернет размер массива (т.е. никакого неявного преобразования в указатель не будет).

__>>это не операция типа в исходном смысле (операция, определяющая допустимые действия над значениями, входящими в данный тип). массив и без нее останется массивом (а вот без операции разындексации массив как общепринятый тип данных исчезнет).
A>Понятно, что если мы будем считать массивом только то, для чего можно выполнить разындексацию, то без разындексации это перестанет быть массивом в нашем понимании.
A>Но массив в первую очередь это непрерывная последовательность однотипных данных, а уж как обращаться к этим элементам, через [] или *+ дело десятое.

не совсем. таким свойством (непрерывная последовательность однотипных данных) обладают и структуры (если использовать директиву pack и однотипные поля). но не будете же вы говорить, что массивы — частный случай структур так что набор данных без указания операции доступа к ним не определяет тип.
Re[11]: Функции для массивов и указателей
От: alexolut  
Дата: 26.11.15 14:56
Оценка:
Здравствуйте, _hum_, Вы писали:

__>то есть, я так понял, вы согласны с тем, что, де-юре, у типа "массив" нет своей собственной операции разындексации

Есть она или нет это не важно, т.к. результат интерпретируется так же как и для обычного указателя. Изменить это поведение для встроенного типа массива нельзя.
Единственное различие в наименовании полученного результата: для указателя это просто значение с учетом смещения, а для массива это будет называться N-ым членом массива.

A>>Но массив в первую очередь это непрерывная последовательность однотипных данных, а уж как обращаться к этим элементам, через [] или *+ дело десятое.

__>не совсем. таким свойством (непрерывная последовательность однотипных данных) обладают и структуры (если использовать директиву pack и однотипные поля). но не будете же вы говорить, что массивы — частный случай структур так что набор данных без указания операции доступа к ним не определяет тип.
Структуры называть массивами, конечно, не буду. Просто не стоило моё предложение интерпретировать как полное и самодостаточное определение того, что есть массив.
Можно добавить, что массив задается типом и кол-вом членов, а для структуры требуется задавать тип и (в большинстве случаев) имя каждого члена отдельно. При этом структуры могут помимо членов-данных иметь и функции-члены, различные вложенные типы и спецификаторы доступа к членам.
Re[12]: Функции для массивов и указателей
От: _hum_ Беларусь  
Дата: 26.11.15 15:27
Оценка:
Здравствуйте, alexolut, Вы писали:

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


__>>то есть, я так понял, вы согласны с тем, что, де-юре, у типа "массив" нет своей собственной операции разындексации

A>Есть она или нет это не важно, т.к. результат интерпретируется так же как и для обычного указателя. Изменить это поведение для встроенного типа массива нельзя.

важно с концептуальной точки зрения — есть собственная операция, или приходится пользоваться чужой (самостоятельный это тип, или только его отголоски).

A>>>Но массив в первую очередь это непрерывная последовательность однотипных данных, а уж как обращаться к этим элементам, через [] или *+ дело десятое.

__>>не совсем. таким свойством (непрерывная последовательность однотипных данных) обладают и структуры (если использовать директиву pack и однотипные поля). но не будете же вы говорить, что массивы — частный случай структур так что набор данных без указания операции доступа к ним не определяет тип.
A>Структуры называть массивами, конечно, не буду. Просто не стоило моё предложение интерпретировать как полное и самодостаточное определение того, что есть массив.
A>Можно добавить, что массив задается типом и кол-вом членов, а для структуры требуется задавать тип и (в большинстве случаев) имя каждого члена отдельно.

ну, так я ж и говорю, в вашем варианте массив — это частный случай структуры вида
template<typename T> struct{ T _0; T _1; T _2; <...> };

(тоже однотипные члены, тоже не требуют задания имени (ибо имена всегда стандартные _0, _1, и т. д.))

A>При этом структуры могут помимо членов-данных иметь и функции-члены, различные вложенные типы и спецификаторы доступа к членам.


ну, это в с++. а структуры есть и в обычном си.
Re[13]: Функции для массивов и указателей
От: alexolut  
Дата: 26.11.15 15:55
Оценка:
Здравствуйте, _hum_, Вы писали:

__>важно с концептуальной точки зрения — есть собственная операция, или приходится пользоваться чужой (самостоятельный это тип, или только его отголоски).

Массив — тип самостоятельный. Но насчет важности я не согласен, т.к. как это реализовано в том или ином компиляторе для программиста, как потребителя, совершенно безразлично.
Он не сможет никак уловить эту разницу.

__>ну, так я ж и говорю, в вашем варианте массив — это частный случай структуры вида

__>
__>template<typename T> struct{ T _0; T _1; T _2; <...> }; 
__>

__>(тоже однотипные члены, тоже не требуют задания имени (ибо имена всегда стандартные _0, _1, и т. д.))
Любой объект есть область памяти. А дальше уже идут частные случаи.

A>>При этом структуры могут помимо членов-данных иметь и функции-члены, различные вложенные типы и спецификаторы доступа к членам.

__>ну, это в с++. а структуры есть и в обычном си.
Они много где есть. Но в данной теме речь всё же о C++ (т.к. в си нет перегрузки функций, о которых упомянул ТС).
Re[14]: Функции для массивов и указателей
От: _hum_ Беларусь  
Дата: 26.11.15 16:06
Оценка:
Здравствуйте, alexolut, Вы писали:

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


__>>важно с концептуальной точки зрения — есть собственная операция, или приходится пользоваться чужой (самостоятельный это тип, или только его отголоски).

A>Массив — тип самостоятельный. Но насчет важности я не согласен, т.к. как это реализовано в том или ином компиляторе для программиста, как потребителя, совершенно безразлично.
A>Он не сможет никак уловить эту разницу.

__>>ну, так я ж и говорю, в вашем варианте массив — это частный случай структуры вида

__>>
__>>template<typename T> struct{ T _0; T _1; T _2; <...> }; 
__>>

__>>(тоже однотипные члены, тоже не требуют задания имени (ибо имена всегда стандартные _0, _1, и т. д.))
A>Любой объект есть область памяти. А дальше уже идут частные случаи.

если так смотреть, то в языках программирования (для пк) нет вообще никаких типов, кроме типа целых чисел, ибо в конечном счете любой объект — это набор двоичных чисел в памяти машины

A>>>При этом структуры могут помимо членов-данных иметь и функции-члены, различные вложенные типы и спецификаторы доступа к членам.

__>>ну, это в с++. а структуры есть и в обычном си.
A>Они много где есть. Но в данной теме речь всё же о C++ (т.к. в си нет перегрузки функций, о которых упомянул ТС).

не, это мы уже оффтопим на тему — "насколько массив является самостоятельным типом (не сводится к указателю на буфер данных), и насколько это естественно реализовано в с++".
Re[3]: Функции для массивов и указателей
От: sokel Россия  
Дата: 29.11.15 09:53
Оценка:
Здравствуйте, johny5, Вы писали:

J>К примеру, из массива можно вытащить его длину, этим мы экономим на strlen операции. С указателем размер строки утерян.


Проблема только в том, как отличить литерал от массива, заполненного вручную и не до конца.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.