Я смотрю на некоторый код, относящийся к 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());
}
Как уже отмечалось, имена аргументов не являются обязательными. Но почему это было опущено, и почему есть аргумент без имени?
Используемая здесь техника — это вычет типа тега шаблона функции, основанный на типах аргументов.
Ты можешь позвонить test_for_each
передавая экземпляр произвольного типа в качестве 2-го параметра. Какой бы тип значения для этого аргумента не передавался template
функционировать как IteratorTag
,
Внутри класса значение IteratorTag
переменная не используется — нам важен только тип.
IteratorTag
s используются, чтобы различать различные виды 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
вариант, как в сторону.
Если вам на самом деле не нужно значение параметра, но вы должны предоставить определенный интерфейс, вы можете использовать безымянный параметр. Это правильный способ заставить замолчать (важное) предупреждение о неиспользованном параметре.
В прототипе функции имена аргументов являются необязательными. Они могут быть полезны в качестве документации, но они не используются компилятором каким-либо значимым образом.
В определении функции, если аргумент не используется в теле функции, его имя снова необязательно:
Foo some_function(Bar bar, Baz)
{
// this is the body of a function that
// does not use its second argument
}
Имя аргумента опущено в следующих случаях использования, о которых я могу думать:
Виртуальный член функции. Реализация производного класса может или не может нуждаться в аргументе. Если аргумент не нужен, разработчик может его опустить.
Чтобы разрешить функцию перегрузки, основанную только на типе, где значение аргумента бесполезно.