• Что означают A.Type и A.self, где A - некий класс, в языке Swift?

    Для любого типа T, T.Type - это метатип (metatype), то есть тип, объекты которого предоставляют описание типа T. Статические функции и init-функции T становятся функциями-членами T.Type. Пример:

    struct Duck {
        static func kind() -> String { return "Bird" }
        init() { }
        func talk() { print("Quack") }
    }
    
    let meta: Duck.Type = Duck.self
    meta.kind()  //=> Bird
    let obj: Duck = meta.init()
    obj.talk()  //=> Quack


    Существует 2 класса метатипов, но на практике встречаются existential metatypes, то есть их объекты могут описывать как данный тип T, так и любой наследник (subtype) типа T. Другими словами, множество объектов типа T.Type - это U.self для всех типов U: T. Пример:

    class Animal { class var name: String { return "Animal" } }
    class Cat: Animal { override class var name: String { return "Cat" } }
    class Dog: Animal { override class var name: String { return "Dog" } }
    
    var meta: Animal.Type
    meta = Cat.self
    meta.name  //=> Cat
    meta = Dog.self
    meta.name  //=> Dog


    Или, например, можно представить себе такую функцию генерации животных:

    class Animal { ... }
    
    func createAnimal(_ type: Animal.Type) -> Animal {
        if type == Cat.self {
            return Cat(...)
        } else if type == Dog.self {
            return Dog(...)
        } else {
            fatalError()
        }
    }


    На практике, такая функциональность метатипов используется редко. Как правило, они служат для явной специализации шаблонных функций. Например:

    func unsafeCast<T, U>(_: T, to: U.Type) -> U

    Здесь единственный способ указать тип U при вызове - это передать "фиктивный" параметр тип U.Type, так как аргументов типа U функция не принимает. Вернее, это лучший и принятый в Swift способ. Можно было бы выкрутиться вот так:

    func unsafeCast<T, U>(_: T, sameAs: U) -> U

    Но, понятно, что для этого нужно иметь под рукой объект типа U, и это не идеальный вариант. Жаль, что нельзя писать просто unsafeCast<U>(t) при вызове.

    При использовании метатипа U.Type таким образом, его значение, как правило, игнорируется. То есть даже если вы передадите туда метатип наследника типа U, то функция всё равно будет работать с U.

    P.S. Есть ещё много недокументированных фич метатипов в Swift, но там всё не очень логично и продуманно (даже разработчики из Core team не всё там понимают), так что на практике лучше ограничиться применением для явной специализации функций, как показано выше.
    Ответ написан
    1 комментарий
  • Строка - образец (шаблон) в СИ - что это?

    Надо выдать int, где бит 0 выставлен тогда и только тогда, когда первый символ строки совпадает с первым символом образца, бит 1 выставлен - когда второй символ строки совпадает со вторым символом образца, и т.д.

    В примере, насколько я понял, надо выдать число, равное 101101111 в двоичной системе.
    Ответ написан
  • Как изменить значение поля enum в рантайме?

    Вам нужны tagged union. Вот как это выглядело бы на Swift, например:

    enum Foo {
        case qqq(Int)
        case www(Int)
    }
    
    let x = Foo.qqq(5)
    let y = Foo.www(10)


    На C++ это часто эмулируется с помощью наследования:

    class Foo {
    public:
        virtual ~Foo() = 0;
    };
    
    class qqq : public Foo {
    public:
        int value;
        explicit qqq(int value);
    };
    
    class www : public Foo {
    public:
        int value;
        explicit www(int value);
    };
    
    using FooPtr = std::unique_ptr<Foo>;
    FooPtr makeQqq(int value);
    FooPtr makeWww(int value);
    
    FooPtr x = makeQqq(5);
    FooPtr y = makeWww(10);


    Я опустил небольшое количество кода, который, я не сомневаюсь, вы могли бы сами закончить, если действительно хотите заставить этого монстра работать :)

    Есть и более чистый способ: подключите либу type_safe (кликабельно).

    #include <type_safe/strong_typedef.hpp>
    #include <type_safe/variant.hpp>
    
    namespace ts = type_safe;
    
    using qqq = ts::strong_typedef<int>;
    using www = ts::strong_typedef<int>;
    using Foo = ts::variant<qqq, www>;
    
    // ...
    
    auto x = Foo(qqq(5));
    auto y = Foo(www(10));
    
    if (x.has_value(ts::variant_type<qqq>{})) {
        qqq value = x.value(ts::variant_type<qqq>{}));
        std::cout << "qqq" << ' ' << static_cast<int>(value);
    }
    Ответ написан
    Комментировать
  • Как вывести на экран все содержимое массива?

    При помощи этой либы:
    fmt::print("Total: [{}]\n", fmt::join(total_1.begin(), total_1.end(), ", "));
    //=> Total: [1, 2, 3]
    Может, кто-то ещё переметнётся на сторону printf-стиля :]
    Ответ написан
  • В visual studio 2017 нету опции создать Win32 Console App,что делать?

    Консольное предложение видовс - это и есть Win32 Console App.
    Ответ написан
    1 комментарий
  • Каким спосабом обработать JSON в Swift 3?

    Подключите либу для парсинга JSON, например, раз, два, три.

    case .success:
        let json = JSON(response.result.value)
        let username: String? = json["People0"]["Name"].string
        // ...


    Обнаружилось, что передаваемый JSON был в не совсем корректном формате, из-за этого придётся делать вот так:

    case .success:
        let json = JSON(response.result.value)
        let nestedJson = JSON(parseJSON: json["People0"].string ?? "{}")
        let username: String? = nestedJson["Name"].string
        // ...
    Ответ написан
  • Нет навыков в программировании, можно ли сразу начать изучать swift?

    Swift - это отличный первый язык программирования. "База" не нужна, если вы хотите писать простенькие графические приложения. Но прежде, чем делать что-то полезное, убедитесь, что вы знаете сам Swift. Скачайте XCode. Его часть Swift Playgrounds - анимированные учебники-задания от Apple. Советую Learn to Code 1, 2, 3. Если где-то застопорились, всегда можно нагуглить гайды/подсказки/советы. Единственное, без чего нельзя начать - английский язык.
    Ответ написан
    Комментировать
  • Как решить задачу на dictionaries из книги?

    Начиная с Swift 4, следующее решение более короткое:

    func occurencesOfCharacters(in text: String) -> [Character: Int] {
      return Dictionary(text.map{ ($0, 1) }, uniquingKeysWith: { $0 + $1 })
    }
    print(occurencesOfCharacters(in: "memerr"))

    Как это работает
    В Swift 4, .characters не нужно, так как строки - это последовательности символов.
    Код text.map{ ($0, 1) } даёт последовательность вида ("m", 1), ("e", 1), ...
    Конструктор Dictionary превращает эту последовательность в словарь вида ["m": 1, "e": 1, ...].
    Когда этот конструктор встречает две пары с одинаковыми ключами, он мержит их значения по указанному правилу, по сути, подсчитывая количество вхождений данного символа.

    Замечу, что решение от DevMan, выписанное "вручную", должно работать более быстро, так как там нет промежуточного представления в виде последовательности кортежей. Но только если убрать двойное обращение к Dictionary на каждой итерации.

    Edit: Этот код должен чуть быстрее работать. Мог бы быть ещё быстрее, но увы, в Dictionary нет для этого некоторых нужных методов.
    func occurencesOfCharacters(in text: String) -> [Character: Int] {
      var dicOfChars: [Character: Int] = [:]
      for character in text.characters {
        dicOfChars[character] = (dicOfChars[character] ?? 0) + 1
      }
      return dicOfChars
    }
    print(occurencesOfCharacters(in: "memerr"))
    Ответ написан
    1 комментарий
  • Почему функция rand() возвращает одно и то же значение?

    Раз уж у вас C++, то от использования rand() вообще лучше отказаться и пользоваться более точной C++-ной либой <random>:

    // Важно: создание этого объекта занимает некоторое время,
    // его лучше использовать для генерации всех случайный чисел
    std::default_random_engine engine(std::random_device()());
    
    // Легковесный объект-диапазон для генерации целых чисел
    // В std есть и куча других полезных распределений
    std::uniform_int_distribution<int> distribution(min,max);
    
    for (int i = 0; i < N; ++i) {
        int random_number = distrubution(engine);
        std::cout << random_number << std::endl;
    }
    Ответ написан
    Комментировать
  • Как сделать std::list размером в 12 байтов?

    1. Скопировать std::list из хедеров VS2003 в свой хедер my_list.h
    2. Переименовать этот std::list в класс (не std) my_list
    3. Использовать my_list вместо std::list при работе с библиотекой
    4. Если там в хедерах прописан std::list&, то при вызове функции можно передавать reinterpret_cast<std::list&>(my_list_instance), чтобы пропихнуть тот список,
      который нужен либе
    Ответ написан
    Комментировать
  • Почему выдает ошибку-неоднозначный вызов перегруженной функции?

    1. Вместо #include <math.h>, в C++ нужно использовать #include <cmath>. Она более производительна в некоторых случаях, и там есть больше функций для C++.
    2. Зачем вводить int, если всё равно вычисляем double? Тогда программа не сойдёт с ума при больших координатах.
    3. Вместо x*x можно использовать pow(x,2) без потери производительности.

    Итого:
    #include <iostream>
    #include <cmath>
    #include <iomanip>
    using namespace std;
    
    int main()
    {
        double x1, x2, y1, y2;
        cin >> x1 >> x2 >> y1 >> y2;
        cout << fixed << setprecision(2) << sqrt(pow(x2 - x1, 2) + pow(y2 - y1, 2));
        return 0;
    }
    Ответ написан
    Комментировать
  • Какая разница в опционалах в Swift?

    Implicitly Unwrapped Optional, в целом, ведут себя как Optional. На самом деле, они преобразовываются к Optional при каждом удобном случае:

    let x: Int! = 42
    let y = x   // y has type Int?

    Есть два отличия: во-первых, можно привести IUO к non-optional типу:

    func f(_ arg: Int) { print(arg) }
    
    let x: Int! = 42
    
    let y: Int = x
    let z = x as Int
    f(x)

    Во-вторых, можно вызывать на такой переменной методы самого объекта. Если в IUO содержится nil, то приложение упадёт с соответствующим сообщением:

    struct Dog {
        func bark() { print("Woof!") }
    }
    
    let d: Dog! = Dog()
    d.bark()

    Применяются IUO, в основном для отложенной инициализации:

    class Foo {
        var x: Int!
    
        init() {
            // I can't setup x at this point :(
            x = nil
        }
    
        func setup(x newValue: Int) { x = newValue }
    
        func foo() {
            // I promise that setupX() will be called before
            // I will deal with x as if it was always present
            print(x * 2)
        }
    }

    Замечу, что, начиная со Swift 3, IUO - это вовсе не тип, а лишь атрибут переменной, который разрешает неявные преобразования с ней. "Под капотом" всё выглядит как-то так:

    let x: Int! = 42
    @implicitlyUnwrapped let x: Optional<Int> = .some(42)
    Ответ написан
    Комментировать
  • Что означает char **s на языке Си?

    char* - это по соглашению Си-строка, то есть указатель на буфер символов, оканчивающийся нулевым байтом '\0'. Для любого типа T, кроме, вероятно, char, T* может быть массивом, а именно, указателем на его первый элемент. Соответственно, char** s - это, скорее всего, массив строк. s[2] - это указатель на третью строку, s[2][3] - это четвёртый символ третьей строки.
    Ответ написан
  • Как изменить глобальную переменную контроллера?

    Возможно, UserService.getUsers - это асинхронная операция. В этом случае код в замыкании выполнится позже, чем код после вызова getUsers.
    Ответ написан
    1 комментарий
  • Как преобразовать float в string с форматированием?

    Можно использовать std::stringstream. Но лучше подключить библиотеку fmt.
    Ответ написан
    Комментировать
  • Можно ли инициализировать статический массив алгоритмом?

    В C++14 для этого есть constexpr-функции:

    #include <iostream>
    #include <array>
    
    template<typename T, size_t n>
    constexpr T& at(std::array<T, n>& a, size_t i) {
        return const_cast<T&>(static_cast<const std::array<T, n>&>(a)[i]);
    }
    
    template<typename T, size_t n>
    constexpr const T& at(const std::array<T, n>& a, size_t i) {
        return a[i];
    }
    
    constexpr std::array<int, 20> generate_fib() {
        auto result = std::array<int, 20>{};
        for (size_t i = 0; i < 20; ++i) {
            if (i < 2) {
                at(result, i) = 1;
            } else {
                at(result, i) = at(result, i-1) + at(result, i-2);
            }
        }
        return result;
    }
    
    constexpr static const auto fib = generate_fib();
    
    int main()
    {
        for (auto elem : fib) {
            std::cout << elem << ' ';
        }
        return 0;
    }

    Скомпилировать онлайн на GCC6.

    Ограничения:
    1. В C++14 не предусмотрели constexpr для std::array::operator[]. Обещают исправить в C++17, а пока имеем костыль в виде функции at.
    2. Ни одна из текущих версий Visual Studio не способна скомпилировать данный код. M$ не дружит с constexpr.
    Ответ написан
  • Как присвоить строку перемененной типа char[]?

    char s1[7] = "hello";

    Ошибки:
    1. Строки нужно заключать в двойные кавычки, а символы в одинарные: 'h', но "hello".
    2. Массивы и строки нельзя присваивать. Исключение составляет инициализация.
    Ответ написан
    1 комментарий
  • Swift или Objective-С: iOS. Книги, видеоуроки?

    Советую официальную документацию Swift Programming Language. Прочтите Language Guide от корки до корки. Копируйте и запускайте примеры, возьмите любой сборник программистких задачек (язык не важен) и решайте на Swift.
    Ответ написан
    1 комментарий
  • Как отсортировать массив с чередованием по два знака?

    1. Отфильтровать положительные элементы в один новый std::vector, отрицательные в другой std::vector
    2. Выводить группами по 4 элемента: 2 из первого вектора, 2 из второго
    Ответ написан
    2 комментария