Pull to refresh
4
0

Senior Engine Programmer

Send message

буквально любая функция, так как void* можно реинтерпретировать как что угодно

void* нельзя привести к указателю на функцию, как минимум потому что размер указателя на функцию может иметь другой размер. См https://godbolt.org/z/nhxjT9r5W

Как я уже написал выше, я не добавлял каких то проверок и не тестировал на всевозможных аргументах, цель этого кода показать принцип решения где используя tuple и index sequence мы простым перебором находим нужные индексы аргументов и затем передаем их в apply. Что касается ошибки в приведенных вами тестах, фикситься одной строчкой. using SourceArgs = std::tuple<std::remove_reference_t<T>...>;

https://godbolt.org/z/YfK11hG5G

Не исключаю, что могут быть и другие ошибки если использовать всевозможные ссылочные типы, const, volatile в качестве аргументов, но опять же это все можно пофиксить.

Реализация для любой функции с любым количеством аргументов (*больше 1) и perfect forwarding. Я не добавлял дополнительные проверки на количество аргументов и т.д. что бы сохранить читабельность кода, при желании можно их добавить.

#include <iostream>
#include <tuple>
#include <type_traits>
#include <string_view>

void do_something(bool a, int b, std::string_view c)
{
	std::cout << c << " " << b << " " << std::boolalpha << a << std::endl;
}

template<typename R, typename... Args>
struct FunctionSignature;

template<typename R, typename... Args>
struct FunctionSignature<R(*)(Args...)> {
	using args_t = std::tuple<Args...>;
	using result_t = R;
};

template <class T, class Tuple>
struct TupleIndex;

template <class T, class... Types>
struct TupleIndex<T, std::tuple<T, Types...>> {
	static inline constexpr std::size_t value = 0;
};

template <class T, class U, class... Types>
struct TupleIndex<T, std::tuple<U, Types...>> {
	static inline constexpr std::size_t value = 1 + TupleIndex<T, std::tuple<Types...>>::value;
};

template<typename SourceTuple, typename TargetTuple, std::size_t... I>
constexpr auto BindIndexes(std::index_sequence<I...>) {
	return std::integer_sequence<std::size_t, TupleIndex<std::tuple_element_t<I, TargetTuple>, SourceTuple>::value...>{};
}

template<typename F, typename Tuple, std::size_t... I>
constexpr decltype(auto) Apply(F&& f, Tuple&& tuple, std::index_sequence<I...>) {
	return std::invoke(std::forward<F>(f), std::get<I>(std::forward<Tuple>(tuple))...);
}

template<typename F, typename... T>
constexpr decltype(auto) InvokeRandomArgs(F&& f, T&&... args) {
	using SourceArgs = std::tuple<T...>;
	using SourceSequence = std::index_sequence_for<T...>;
	using TargetArgs = typename FunctionSignature<F>::args_t;

	return Apply(std::forward<F>(f), std::forward_as_tuple(std::forward<T>(args)...), BindIndexes<SourceArgs, TargetArgs>(SourceSequence{}));
}

int main()
{
	InvokeRandomArgs(&do_something, std::string_view{ "Hello" }, true, 20);
	InvokeRandomArgs(&do_something, false, 40, std::string_view{ "World" });
	InvokeRandomArgs(&do_something, 14, std::string_view{ "C++" }, true);
	InvokeRandomArgs(&do_something, 17, true, std::string_view{ "std" });

	return 0;
}
на данный момент альтернатив CMake просто не существует.

Возможно Вам стоит взглянуть на Sharpmake, продукт написанный и используемый внутри Ubisoft, недавно был опубликован на github. Не знаю можно ли тут выкладывать ссылку, легко гуглится. Хоть это и урезанная версия, например не содержит готовых настроек для консолей, но это из-за требований first party, что в прочем не мешает вам их добавить. В целом позволяет очень быстро генерировать огромные проекты под Visual Studio, XCode или makefile's, а главное очень гибкая и простая настройка т.к. все написано на C#, вы можете включить в генератор абсолютно любую логику, платформы и сборки.
Например на проекте в несколько миллионов строк кода, над которым я сейчас работаю, Sharpmake генерирует solution для Visual Studio под 5 различных платформ, debug|release|profile|retail + blob + fastbuild меньше чем за минуту на 8ми ядерном процессоре.
Да, если тип size_t будет несовместимый с эффективным типом data.
В C++ не хватает такой сущности как interface, — структурой в которой такая оптимизация была бы включена по умолчанию и компилятор, который выдавал ошибку если в интерфейс добавить что либо кроме виртуальных функций.
Условие «реализация функции вывода на печать не в счет» подразумевает, что ее возвращаемое значение тоже часть реализации и можно использовать саму функцию printf как условие.
int main()
{
	int n = 9;
	while (printf("%.d", n--));
	printf("0");

	return 0;
}


Однако тут используется цикл с условием. Если брать в широком смысле, то так или иначе задача не решаема без цикла или рекурсии, но рекурсия ограничена. Если исключить любое сравнение то подходит только бесконечный цикл.
Прервать его можно следующими способами:
1. break
2. return из main фунции
3. Бросить исключение
4. goto
5. Функция exit() или ее аналоги

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

#include <cstdio>
#include <stdlib.h>

void print(int n) { printf("%d\n", n); }
void printAndExit(int n) { print(n); exit(0); };
void(*f[])(int) = { printAndExit, print };

int main()
{
	int n = 9;
	for (;;)
	{
		f[bool(n)](n);
		--n;
	}

	return 0;
}
Если уж использовать С++, то все проще некуда.

int main()
{
const int n = 10;
int count = n;
std::generate_n(std::ostream_iterator(std::cout, " "), n, [&count]() { return count--; });

return 0;
}


Много текста и страшных преобразований, которые сводятся к одной простой сути — массивы в стеке и на куче работают по разному. Если с одномерными массивами особо проблем нету и они легко преобразуются к указателю, то с многомерными надо помнить что «Массив массивов» и «указатель на указатель» — это разные сущности. Можно легко наступить на грабли если не знать этих особенностей и потому лучше избегать использования двумерных статических массивов.
Если соединить углы линиями и вычислить перспективу можно ли создать 3D модель объекта по фотографии?
Пишу код — не отдыхаю
И почему никто раньше не догадался использовать никель? Это довольно распространненый метал, да и опыт не сложный.
На плюсах таких способов много, вот один из них.

std::vector<int> vec(10000);
std::iota(vec.begin(),vec.end(),1);
std::copy(vec.begin(),vec.end(),std::ostream_iterator<int>(std::cout, ", "));
Просто странно наблюдать такую статистику. Казалось бы, сотрудники, которые лояльны компании и хорошо разбираются в ее проектах должны ценится больше, а выходит наоборот.
Что-то в этом мире определенно не так.
Дождаться бы еще создания полностью автоматизированного оркестра способного исполнять классические симфонии.
А я обрадовался, зарегистрировался, а потом глянул цену и даже в бету не хочется теперь играть. Вдруг понравится.
Payoneer не является электронной валютой.
Насколько я знаю, нету. Книга была опубликована в 1994, а все дальнейшие изменения в языке после 1994 года были сделаны комитетом по стандартизации.
А про С++ Страуструп неплохо рассказывает тут.
Если кому интересно более детально узнать как развивался C++ советую почитать
вот это.
1

Information

Rating
Does not participate
Location
Mainz, Rheinland-Pfalz, Германия
Date of birth
Registered
Activity