Неименованные параметры функции

Я смотрю на некоторый код, относящийся к n3960 стандартное предложение и заметил, что некоторые функции имеют параметры без имени, но имеют полное определение функции. Может кто-нибудь объяснить, как это?

Пример:

template <typename ExPolicy, typename IteratorTag>
void test_for_each(ExPolicy const& policy, IteratorTag) //just IteratorTag, no name?
{
BOOST_STATIC_ASSERT(hpx::parallel::is_execution_policy<ExPolicy>::value);

typedef std::vector<std::size_t>::iterator base_iterator;
typedef test::test_iterator<base_iterator, IteratorTag> iterator;

std::vector<std::size_t> c(10000);
std::iota(boost::begin(c), boost::end(c), std::rand());

hpx::parallel::for_each(policy,
iterator(boost::begin(c)), iterator(boost::end(c)),
[](std::size_t& v) {
v = 42;
});

// verify values
std::size_t count = 0;
std::for_each(boost::begin(c), boost::end(c),
[](std::size_t v) {
HPX_TEST_EQ(v, std::size_t(42));
++count;
});
HPX_TEST_EQ(count, c.size());
}

1

Решение

Как уже отмечалось, имена аргументов не являются обязательными. Но почему это было опущено, и почему есть аргумент без имени?

Используемая здесь техника — это вычет типа тега шаблона функции, основанный на типах аргументов.

Ты можешь позвонить test_for_each передавая экземпляр произвольного типа в качестве 2-го параметра. Какой бы тип значения для этого аргумента не передавался template функционировать как IteratorTag,

Внутри класса значение IteratorTag переменная не используется — нам важен только тип.

IteratorTags используются, чтобы различать различные виды std Итераторы библиотеки — прямой, произвольный доступ, ввод, вывод и т. д.

Имея этот тип в руках, мы можем вносить незначительные изменения в поведение нашего кода (или менее тонкие, используя перегрузку). В этом случае iterator Тип внутри функции принимает IteratorTag введите как один из его template аргументы, поэтому тип этой переменной отличается в зависимости от IteratorTag прошло в.

Вот простая версия этого с использованием тега для техники, называемой «диспетчеризация тегов»:

template<typename T>
int floor_to_int( T&& t, std::true_type ) { return std::forward<T>(t); }
template<typename T>
int floor_to_int( T&& t, std::false_type ) { return floor(std::forward<T>(t)); }
template<typename T>
int smart_floor( T&& t ) {
return floor_to_int( std::forward<T>(t), std::is_integral< typename std::decay<T>::type >{} );
}

здесь smart_floor функция принимает произвольный тип Tи тогда и только тогда, когда это вызовы нецелого типа floor в теме. В противном случае он просто преобразует его в int,

Мы создаем экземпляр типа тега — в этом случае std::is_integral< typename std::decay<T>::type > — и передать его внутренней вспомогательной функции. В этом случае у нас есть две перегрузки, ни одна из которых не использует значение переданного тега, только его тип.

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

Вероятность того, что аргумент здесь должен быть std::iterator_traits< T >::iterator_category или какой-то доморощенный boost вариант, как в сторону.

6

Другие решения

Если вам на самом деле не нужно значение параметра, но вы должны предоставить определенный интерфейс, вы можете использовать безымянный параметр. Это правильный способ заставить замолчать (важное) предупреждение о неиспользованном параметре.

3

В прототипе функции имена аргументов являются необязательными. Они могут быть полезны в качестве документации, но они не используются компилятором каким-либо значимым образом.

В определении функции, если аргумент не используется в теле функции, его имя снова необязательно:

Foo some_function(Bar bar, Baz)
{
// this is the body of a function that
// does not use its second argument
}
1

Имя аргумента опущено в следующих случаях использования, о которых я могу думать:

  1. Виртуальный член функции. Реализация производного класса может или не может нуждаться в аргументе. Если аргумент не нужен, разработчик может его опустить.

  2. Чтобы разрешить функцию перегрузки, основанную только на типе, где значение аргумента бесполезно.

0
По вопросам рекламы [email protected]