Различные типы функций

342
05 апреля 2019, 21:00

Не очень понимаю, почему следующий код выводит 0 1 0. Какие типы у foo_1, foo_2 и foo_3?

void foo() {}
int main() {
    using foo_1 = decltype(foo);
    using foo_2 = const foo_1&;
    using foo_3 = foo_1&;

    std::cout << std::is_same_v<foo_1, foo_2> << '\n'
              << std::is_same_v<foo_2, foo_3> << '\n'
              << std::is_same_v<foo_1, foo_3> << '\n';
}

Тем более на gcc следующий код даёт одинаковые значения

std::cout << typeid(foo_1).name() << '\n'
          << typeid(foo_2).name() << '\n'
          << typeid(foo_3).name() << '\n';
Answer 1

foo_2 и foo_3 являются ссылками на функцию (причём const для foo_2 проигнорирован и эти типы вообще полностью идентичны). В то время как foo_1 тип - функция (не указатель на функцию). Поэтому и получается такой результат в std::is_same_v. Несколько примеров:

#include <iostream>
void f() {}
int main() 
{
    using F = decltype(f); // тип функции
    using FR = void(&)();  // тип ссылки на функцию
    using FP = void(*)();  // тип указателя на функцию (using форма)
    typedef void (*FP2)(); // тип указателя на функцию (typedef форма)
    std::cout << std::boolalpha;
    std::cout << std::is_same_v<F, void()> << "\n";     // true  (F - функция)
    std::cout << std::is_same_v<F, FR> << "\n";         // false (F - не ссылка на функцию)
    std::cout << std::is_same_v<F, FP> << "\n";         // false (F - не указатель на функцию)
    std::cout << std::is_same_v<FP, FP2> << "\n";       // true  (FP и FP2 одно и то же, заданное разными способами)
    std::cout << std::is_same_v<F&, FR> << "\n";        // true  (F& - ссылка на функцию)
    std::cout << std::is_same_v<const FR, FR> << "\n";  // true  (const не влияет на тип ссылки на функцию)
    std::cout << std::is_same_v<const F, F> << "\n";    // true  (const не влияет на тип функции)    
    std::cout << std::is_same_v<const FP, FP> << "\n";  // false (const влияет на тип указателя на функцию)    
}

При этом typeid(/* */).name() даёт одинаковые результаты потому, что для ссылок и значений он работает единообразно, можете попробовать например typeid(int&).name() и typeid(int).name(). А учитывая неявные преобразования между типом функции и типом указателя на функцию одинаковость результата здесь тоже не вызывает особых вопросов.

Answer 2

Тип foo - void (void), foo_2 и foo_3 - void ( & ) (void). const в этом контексте ничего не делает (warning: 'const' qualifier on function type 'foo_1' (aka 'void ()') has no effect [-Wignored-qualifiers])

typeid выдает одинаковые результаты потому что не различает ссылок.

READ ALSO
Не меняются иконки C++

Не меняются иконки C++

Вообщем вот фрагмент кода, код себя ведет не очень понятно, все как бы хорошо, но иконка не меняется при наступлении 19 часов(а так должно быть)

199
Как подключить cURL к Visual Studio?

Как подключить cURL к Visual Studio?

Я скачал архив с сайта, к сделал всё как на видео но мне пишет,

194
Как обвернуть OpenGL на С++ в GNU/Linux

Как обвернуть OpenGL на С++ в GNU/Linux

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

214
Использование Firebase (databasE) в c++

Использование Firebase (databasE) в c++

Всем приветПытаюсь найти хоть какой-нибудь способ использования Firabase'а в C++

216