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
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.Type
, так как аргументов типа U
функция не принимает. Вернее, это лучший и принятый в Swift способ. Можно было бы выкрутиться вот так:func unsafeCast<T, U>(_: T, sameAs: U) -> U
unsafeCast<U>(t)
при вызове.U.Type
таким образом, его значение, как правило, игнорируется. То есть даже если вы передадите туда метатип наследника типа U, то функция всё равно будет работать с U.enum Foo {
case qqq(Int)
case www(Int)
}
let x = Foo.qqq(5)
let y = Foo.www(10)
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-стиля :] case .success:
let json = JSON(response.result.value)
let username: String? = json["People0"]["Name"].string
// ...
case .success:
let json = JSON(response.result.value)
let nestedJson = JSON(parseJSON: json["People0"].string ?? "{}")
let username: String? = nestedJson["Name"].string
// ...
func occurencesOfCharacters(in text: String) -> [Character: Int] {
return Dictionary(text.map{ ($0, 1) }, uniquingKeysWith: { $0 + $1 })
}
print(occurencesOfCharacters(in: "memerr"))
.characters
не нужно, так как строки - это последовательности символов.text.map{ ($0, 1) }
даёт последовательность вида ("m", 1), ("e", 1), ...
Dictionary
превращает эту последовательность в словарь вида ["m": 1, "e": 1, ...]
.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"))
<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
из хедеров VS2003 в свой хедер my_list.h
std::list
в класс (не std) my_list
my_list
вместо std::list
при работе с библиотекойstd::list&
, то при вызове функции можно передавать reinterpret_cast<std::list&>(my_list_instance)
, чтобы пропихнуть тот список,#include <math.h>
, в C++ нужно использовать #include <cmath>
. Она более производительна в некоторых случаях, и там есть больше функций для C++.int
, если всё равно вычисляем double
? Тогда программа не сойдёт с ума при больших координатах.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;
}
let x: Int! = 42
let y = x // y has type Int?
func f(_ arg: Int) { print(arg) }
let x: Int! = 42
let y: Int = x
let z = x as Int
f(x)
struct Dog {
func bark() { print("Woof!") }
}
let d: Dog! = Dog()
d.bark()
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)
}
}
let x: Int! = 42
@implicitlyUnwrapped let x: Optional<Int> = .some(42)
char*
- это по соглашению Си-строка, то есть указатель на буфер символов, оканчивающийся нулевым байтом '\0'. Для любого типа T
, кроме, вероятно, char
, T*
может быть массивом, а именно, указателем на его первый элемент. Соответственно, char** s
- это, скорее всего, массив строк. s[2]
- это указатель на третью строку, s[2][3]
- это четвёртый символ третьей строки. #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;
}
char s1[7] = "hello";