由于我希望能够做到这一点的原因;
vector<int> p = {1, 2};
vector<vector<int>> q = {p, {0, 1}};
auto t = test(p);
auto u = test(q); // Fails with below implementation
特别值得一提的是,test接受自定义类,这些自定义类可能会或可能不会为一个或两个(现在)维度进行迭代。我试图通过检查所提供的内容是否具有size
函数来确定要做什么;
template<typename T> struct hasSize {
template<typename U, size_t(U::*)() const> struct SFINAE {};
template<typename U> static char Test(SFINAE<U, &U::size>*);
template<typename U> static int Test(...);
static const bool value = sizeof(Test<T>(0)) == sizeof(char);
};
template<typename iterable> int test(const iterable &x, std::false_type) {
return (int) x;
}
template<typename iterable> int test(const iterable &x, std:: true_type) {
int total = 0;
for(auto &each : x)
total += test(each,
std::integral_constant<bool, hasSize<decltype(each)>::value>());
return total;
}
template<typename iterable> int test(const iterable &view) {
return test(view, std::true_type());
}
在放弃here答案之后,我基于this给出了答案,因为这似乎只适用于成员变量,而不是函数。我还尝试了在第一次讨论中给出的has_const_reference_op
的修改版本,但这也存在同样的问题。
给出的错误表明第二次没有应用SNIFAE;
error C2440: 'type cast':
cannot convert from 'const std::vector<int, std::allocator<_Ty>>' to 'int'
note: No user-defined-conversion operator available that can perform this conversion,
or the operator cannot be called
note: see reference to function template instantiation
'int test<iterable>(const iterable &, std::false_type)' being compiled
with iterable = std::vector<int,std::allocator<int>>
但我不知道为什么。
答案 0 :(得分:1)
失败的原因是auto&
- 类型变量实际上是const std::vector<int>&
类型iterable
类型const vector<vector<int>>&
,所以当查询{{1 - 它产生的引用类型无法通过SFINAE检查decltype
成员函数存在。因此,不要使用size
,而只需阅读decltype
中的value_type
:
iterable
或从total += test(each, std::integral_constant<bool,
hasSize<typename iterable::value_type>::value
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
>());
生成的类型中移除referenceness / constness:
decltype
答案 1 :(得分:0)
首先,对于将军foreach($array as $sub) {
if(!isset($result[$sub['Country']])) {
$result[$sub['Country']] = array('Country' => $sub['Country'],
'Total Live' => $sub['Live'],
'provider' => 'All Providers',
'status' => 'active',
'# per status' => 'NULL');
} else {
$result[$sub['Country']]['Total Live'] += $sub['Live'];
}
}
$array = array_merge($array, array_values($result));
来说这不是正确的事情:
test()
因为一般template<typename iterable> int test(const iterable &view) {
return test(view, std::true_type());
}
不可迭代 - 这就是我们需要测试的内容!相反,我们将把它转发到命名空间中的一系列三个函数,以便我们可以利用ADL找到我们需要找到的所有内容:
test
我们需要ADL,以便每个功能都可以找到彼此。
请注意,最好编写产生类型而不仅仅是值的类型特征。我们写过类似的东西:
namespace adl {
struct helper {};
template<typename iterable>
int test(helper, const iterable &x, std::false_type) {
return (int) x;
}
template<typename iterable>
int test(helper, const iterable &x, std:: true_type) {
int total = 0;
for(auto &each : x) {
// this calls the general one
total += test(helper{}, each);
}
return total;
}
template <typename iterable>
int test(helper, const iterable& x) {
return test(helper{}, x, std::integral_constant<bool, hasSize<iterable>::value>{});
}
}
template<typename iterable>
int test(const iterable &view) {
return test(adl::helper{}, view);
}
然后我们的测试人员重载可能会短得多:
template <class T, class = void>
struct hasSize : std::false_type { };
template <class T>
struct hasSize<T, void_t<decltype(std::declval<T const&>().size())>>
: std::true_type { };
这可能不适用于VS2013,但您仍然可以向template <typename iterable>
int test(helper, const iterable& x) {
return test(helper{}, x, hasSize<iterable>{});
}
添加type
typedef。