- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
#include <iostream>
#include <string>
#include <string_view>
int main() {
std::string s = "Hellooooooooooooooo ";
std::string_view sv = s + "World\n";
std::cout << sv;
}
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
+4
#include <iostream>
#include <string>
#include <string_view>
int main() {
std::string s = "Hellooooooooooooooo ";
std::string_view sv = s + "World\n";
std::cout << sv;
}
https://alexgaynor.net/2019/apr/21/modern-c++-wont-save-us/
What's happening here is that s + "World\n" allocates a new std::string, and then is converted to a std::string_view. At this point the temporary std::string is freed, but sv still points at the memory that used to be owned by it. Any future use of sv is a use-after-free vulnerability. Oops! C++ lacks the facilities for the compiler to be aware that sv captures a reference to something where the reference lives longer than the referent. The same issue impacts std::span, also an extremely modern C++ type.
+2
// https://github.com/WebKit/webkit/blob/e0e7e8f907f4c01c723374e8230a63d46e89e6a0/Source/WebCore/platform/graphics/filters/FEComposite.cpp#L98
static unsigned char clampByte(int c)
{
unsigned char buff[] = { static_cast<unsigned char>(c), 255, 0 };
unsigned uc = static_cast<unsigned>(c);
return buff[!!(uc & ~0xff) + !!(uc & ~(~0u >> 1))];
}
+2
https://habr.com/ru/article/448466/
*/
А последние пару лет набирает популярность boost.hana. Это boost.fusion,
но с constexpr'ом и лямбдами. Автор hana, Луис Дионе (Louis Dionne),
используя на полную мощь все возможности новых стандартов, в некотором
смысле очеловечил метапрограммирование. С помощью hana всяческие
манипуляции с типами, их кортежами, отображениями, а также компайл- и
рантайм-работа с ними обрели практически человеческое лицо и читаемый
вид. Ну, с поправкой на синтаксис C++, разумеется. Вот, например, как выглядит
универсальный сериализатор структур, написанный с помощью hana:
*/
// 1. Give introspection capabilities to 'Person'
struct Person {
BOOST_HANA_DEFINE_STRUCT(Person,
(std::string, name),
(int, age)
);
};
// 2. Write a generic serializer (bear with std::ostream for the example)
auto serialize = [](std::ostream& os, auto const& object) {
hana::for_each(hana::members(object), [&](auto member) {
os << member << std::endl;
});
};
// 3. Use it
Person john{"John", 30};
serialize(std::cout, john);
/*
Ну да, структуры приходится описывать особым образом. А кому сейчас легко?
И тут хочется также отметить библиотеку tinyrefl за авторством Manu Sánchez
(Мануэля Санчеса). Довольно неплохая попытка принести в мир C++-разработки
статическую рефлексию без расширения компилятора. Для своей работы библиотека
требует стороннюю утилиту (cppast), но зато предоставляет довольно удобный доступ
к информации о структурах, которую можно использовать в процессе разработки
программы. Преимущество этой библиотеки (по сравнению с другими) в том, что для
работы с ней не надо использовать «птичий язык», а элементы структур (как и сами
структуры) можно произвольным образом атрибутировать прямо в исходном коде:
*/
struct [[serializable]] Person {
std::string name;
int age;
};
template<typename Class>
auto serialize(std::ostream& os, Class&& object) -> std::enable_if_t<
tinyrefl::has_metadata<std::decay_t<Class>>() &&
tinyrefl::has_attribute<std::decay_t<Class>>("interesting"),
std::ostream&>
{
tinyrefl::visit_member_variables(object, [&os](const auto& /* name */, const auto& var) {
os << var << std::endl;
});
return equal;
}
/*
Таких примеров можно привести ещё много (или найти на гитхабе или гитлабе).
Объединяет все эти библиотеки и инструменты одна особенность: значительно
облегчая жизнь своим пользователям, они имеют такую реализацию, что остаётся
лишь предполагать, какое количество страданий испытали их разработчики. Достаточно
заглянуть в реализацию, увидеть забор из ifdef'ов и угловых скобок — и всё понятно.
Нередко эти реализации делаются на грани возможностей компиляторов. workaround'ы
банальных ошибок (или особенностей реализации языка конкретной версии конкретного
компилятора с конкретными флагами) здорово раздувают их код. Желание поддерживать
несколько стандартов сразу заставляет придумывать зубодробильные конструкции.
Безусловно, простая попытка реализовать что-нибудь подобное здорово поднимает уровень
владения языком (иногда — и самооценку). Но в какой-то момент, после многочасовой возни
с очередной ошибкой, или непроходящим тестом, или крэшем компилятора руки опускаются,
хочется плюнуть и бросить, ибо силы бороться иссякают.
*/
Именно поэтому я за гомоиконность
+1
#include <type_traits>
int main() { return std::is_assignable_v<int, int>; }
--> 0
WTF?
+1
#include <iostream>
#include <functional>
#include <array>
#include <iterator>
template <class T>
class Filter : public std::iterator<
std::input_iterator_tag,
typename std::iterator_traits<T>::value_type,
typename std::iterator_traits<T>::difference_type,
typename std::iterator_traits<T>::pointer,
typename std::iterator_traits<T>::reference
>
{
private:
typedef typename std::iterator_traits<T>::value_type value_type;
std::function<bool(value_type)> m_predicate;
T m_begin, m_end;
value_type m_current;
public:
Filter(T t_begin, T t_end, std::function<bool(value_type)> t_predicate)
: m_begin(t_begin), m_end(t_end), m_predicate(t_predicate)
{
}
Filter<T>& begin()
{
return ++*this;
}
Filter<T>& end()
{
return *this;
}
value_type operator* ()
{
return m_current;
}
Filter<T>& operator++ ()
{
do {
m_current = *m_begin;
++m_begin;
} while (m_begin != m_end && !m_predicate(m_current));
return *this;
}
bool operator!= (Filter<T>& t_right)
{
return m_begin != t_right.m_end;
}
};
int main()
{
std::array<int, 10> arr{ {4, 35, 0, 23, 0, 0, 5} };
for (auto i : Filter<typename std::array<int,10>::iterator>(arr.begin(), arr.end(), [](int x){return x != 0;})) {
std::cout << i << " ";
}
}
+1
https://en.cppreference.com/w/cpp/language/lambda
> Explanation
> > <tparams>
> Like in a template declaration, the template parameter list may be followed by an optional requires-clause, which specifies the constraints on the template arguments.
> optional requires-clause
небязательные обязательные пункты.
Переводил почти час.
+3
// https://stackoverflow.com/questions/313970/how-to-convert-stdstring-to-lower-case?__=1746193182#
std::transform(data.begin(), data.end(), data.begin(), ::tolower);
Какой багор )))
+4
#include <inttypes.h>
auto a(auto b) __attribute__ ((noinline));
auto a(auto b)
{
return b*1.5;
}
double test1(double in)
{
return a(in);
}
uint64_t test2(uint64_t in)
{
return a(in);
}
/*
https://godbolt.org/z/6ZQAnv
auto a<double>(double):
mulsd xmm0, QWORD PTR .LC0[rip]
ret
test1(double):
jmp auto a<double>(double)
auto a<unsigned long>(unsigned long):
test rdi, rdi
js .L5
pxor xmm0, xmm0
cvtsi2sd xmm0, rdi
mulsd xmm0, QWORD PTR .LC0[rip] # хули ты мне плавучего питуха в xmm0 возвращаешь?
ret
.L5:
mov rax, rdi
and edi, 1
pxor xmm0, xmm0
shr rax
or rax, rdi
cvtsi2sd xmm0, rax
addsd xmm0, xmm0
mulsd xmm0, QWORD PTR .LC0[rip]
ret
test2(unsigned long):
sub rsp, 8
call auto a<unsigned long>(unsigned long)
movsd xmm1, QWORD PTR .LC1[rip]
comisd xmm0, xmm1
jnb .L8
cvttsd2si rax, xmm0 # ну нахуй тут надо double в uint64_t конвертить
add rsp, 8 # почему это не делается в auto a<unsigned long>(unsigned long)
ret
.L8:
subsd xmm0, xmm1
add rsp, 8
cvttsd2si rax, xmm0
btc rax, 63
ret
.LC0:
.long 0
.long 1073217536
.LC1:
.long 0
.long 1138753536
*/
концепты-хуепты
+1
template<typename T>
class IsClassT {
private:
typedef char One;
typedef struct { char a[2]; } Two;
template<typename C> static One test(int C::*);
// Will be chosen if T is anything except a class.
template<typename C> static Two test(...);
public:
enum { Yes = sizeof(IsClassT<T>::test<T>(0)) == 1 };
enum { No = !Yes };
};
Как эта поебота работает?
Что такое "int C::*"?
+2
#include <type_traits>
struct Foo {
void bar(int) const & {}
};
int main() {
using MethodPtr = decltype(&Foo::bar);
const MethodPtr arr[] = { &Foo::bar };
auto *ptr = &arr;
auto &ref = ptr;
static_assert(std::is_same_v<decltype(ref), void (Foo::* const (*&)[1])(int) const &>);
}
Магия указателей возведенная в степень магии массивов в степени магии ссылок.
https://wandbox.org/permlink/8DygQ6oocrEY1K1M