我正在查看一些与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());
}
答案 0 :(得分:6)
如上所述,参数名称是可选的。但是为什么这个被省略了,为什么有一个没有名字的论点?
这里使用的技术是基于参数类型的函数模板标记类型推导。
您可以调用test_for_each
传递任意类型的实例作为第二个参数。无论该参数的值类型如何最终作为template
传递给IteratorTag
函数。
在课堂上,没有使用IteratorTag
变量的值 - 我们关心的只是类型。
IteratorTag
用于区分各种std
库迭代器 - 转发,随机访问,输入,输出等。
掌握了这种类型,我们可以对代码的行为方式进行细微的更改(或者使用重载更轻微)。在这种情况下,函数中的iterator
类型将IteratorTag
类型作为其template
个参数之一,因此该变量的类型根据传入的IteratorTag
而有所不同
以下是一个简单的版本,使用了一种名为&#34;标签调度&#34;的技术标签:
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
变体,作为旁白。
答案 1 :(得分:3)
如果您实际上不需要参数的值,但必须提供某个接口,则可以使用未命名的参数。这是使(重要的)未使用参数警告静音的正确方法。
答案 2 :(得分:1)
在函数原型中,参数名称是可选的。它们可能作为文档很有用,但编译器不会以任何有意义的方式使用它们。
在函数定义中,如果函数体中没有使用参数,则其名称也是可选的:
Foo some_function(Bar bar, Baz)
{
// this is the body of a function that
// does not use its second argument
}
答案 3 :(得分:0)
在以下用例中省略了参数名称,我可以想到:
虚拟会员功能。派生类实现可能需要也可能不需要参数。如果它不需要参数,开发人员可以选择将其删除。
根据参数值无效的类型解决重载函数。