函数模板和 type_traits 的问题
Problems with function template and type_traits
我有一个函数"has_holes",它会根据掩码计算一些东西。位数由"mask"的类型决定。因此我想使用模板。此外,我只想允许 has_holes 的实例化,它按值获取参数。所以我添加了一个 typetrait "remove_all_t" 来给出底层类型。但是当我这样做时,我无法再构建它并收到错误消息:
"error: no matching function for call to 'has_holes(unsigned int&)"
注意:候选模板被忽略:无法推断模板参数 'BASE_TYPE'
但是,如果我显式调用 funktion 实例化“has_holes 它会起作用。
我搞砸了模板实例化和类型推导规则吗?或者我的错误在哪里?
代码如下:
#include <iostream>
#include <limits>
#include <type_traits>
#include <experimental/type_traits>
//removes everything except arrays []
template<class T> struct remove_all { typedef T type; };
template<class T> struct remove_all<T*> : remove_all<T> {};
template<class T> struct remove_all<T&> : remove_all<T> {};
template<class T> struct remove_all<T&&> : remove_all<T> {};
template<class T> struct remove_all<T const> : remove_all<T> {};
template<class T> struct remove_all<T volatile> : remove_all<T> {};
template<class T> struct remove_all<T const volatile> : remove_all<T> {};
template<class T>
using remove_all_t = typename remove_all<T>::type;
template<typename BASE_TYPE, class = typename std::enable_if_t<std::experimental::is_unsigned_v<BASE_TYPE>, BASE_TYPE>>
bool has_holes(remove_all_t<BASE_TYPE> mask){ //remove "remove_all_t<>" and it will work
static_assert(std::numeric_limits<unsigned int>::max() > std::numeric_limits<decltype(mask) >::digits, "Base_type has to much digits max_digits=std::numeric_limits<unsigned int>::max()");
for (unsigned int pos{1}; pos<std::numeric_limits<decltype(mask)>::digits; ++pos ){
;//algorithm will be placed here, not implemented yet
}
return true;
}
int main()
{
unsigned int mask = 0b00110011;
auto result = has_holes<unsigned int>(mask); //works
auto result2 = has_holes(mask);//error: no matching function for call to 'has_holes(unsigned int&)'|
std::cout<<result<<" ..."<<result2<<std::endl;
return 0;
}
此致,
亨德里克
在 C++ 中,模板推导不是无限的。它将拒绝尝试反转可能的图灵完备过程。
C++ 标准将其称为非推导上下文:模板参数不会被推导的上下文。
remove_all_t<BASE_TYPE>
归纳出一个非推导的上下文。因为当您通过 remove_all_t<X>
等模板映射类型时,理论上 映射过程可能是图灵完备的。
一般来说,模板类型映射不会告诉 C++ 如何反转它们。该标准告诉编译器不要尝试。
删除 remove_all_t<BASE_TYPE>
并替换为 BASE_TYPE
,它将始终推导为一个值。
如果你害怕有人将 int&
作为模板类型参数显式传递,请在函数体中添加一个 static_assert( std::is_same<remove_all_t<BASE_TYPE>, BASE_TYPE>::value, "values only");
。
既然你关心的是位数,那么在算出位数的时候做类型缩减就好了。
template<typename BASE_TYPE,
class = typename std::enable_if_t<std::experimental::is_unsigned_v<remove_all_t<BASE_TYPE> > >
>
bool has_holes(BASE_TYPE mask)
{
using reduced_type = remove_all_t<BASE_TYPE>;
static_assert(std::numeric_limits<unsigned int>::max() > std::numeric_limits<reduced_type>::digits,
"Base_type has to many digits max_digits=std::numeric_limits<unsigned int>::max()");
for (unsigned int pos{1}; // really start at 1 (nor 0)?
pos < std::numeric_limits<reduced_type>::digits;
++pos )
{
//algorithm will be placed here, not implemented yet
}
return true;
}
尽管您可能不想接受 BASE_TYPE*
(所以必须修改它)。
模板参数推导已尝试,如[temp.deduct.call]/p1
中所述
P = typename remove_all<BASE_TYPE>::type
和 A = unsigned int
。最终 BASE_TYPE
无法推导(也无法默认),这变成了每个 [temp.deduct.type]/p2
.
的不完整推导
作为旁注,我会使用一个简单的解决方法(因为您已经有其他静态断言)
template<typename BASE_TYPE, class = typename std::enable_if_t<std::experimental::is_unsigned_v<BASE_TYPE>, BASE_TYPE>,
typename RBASE_TYPE = remove_all_t<BASE_TYPE>>
^^^^^^^^^^
bool has_holes(BASE_TYPE mask){
// Use RBASE_TYPE here
return true;
}
我有一个函数"has_holes",它会根据掩码计算一些东西。位数由"mask"的类型决定。因此我想使用模板。此外,我只想允许 has_holes 的实例化,它按值获取参数。所以我添加了一个 typetrait "remove_all_t" 来给出底层类型。但是当我这样做时,我无法再构建它并收到错误消息:
"error: no matching function for call to 'has_holes(unsigned int&)" 注意:候选模板被忽略:无法推断模板参数 'BASE_TYPE'
但是,如果我显式调用 funktion 实例化“has_holes 它会起作用。 我搞砸了模板实例化和类型推导规则吗?或者我的错误在哪里?
代码如下:
#include <iostream>
#include <limits>
#include <type_traits>
#include <experimental/type_traits>
//removes everything except arrays []
template<class T> struct remove_all { typedef T type; };
template<class T> struct remove_all<T*> : remove_all<T> {};
template<class T> struct remove_all<T&> : remove_all<T> {};
template<class T> struct remove_all<T&&> : remove_all<T> {};
template<class T> struct remove_all<T const> : remove_all<T> {};
template<class T> struct remove_all<T volatile> : remove_all<T> {};
template<class T> struct remove_all<T const volatile> : remove_all<T> {};
template<class T>
using remove_all_t = typename remove_all<T>::type;
template<typename BASE_TYPE, class = typename std::enable_if_t<std::experimental::is_unsigned_v<BASE_TYPE>, BASE_TYPE>>
bool has_holes(remove_all_t<BASE_TYPE> mask){ //remove "remove_all_t<>" and it will work
static_assert(std::numeric_limits<unsigned int>::max() > std::numeric_limits<decltype(mask) >::digits, "Base_type has to much digits max_digits=std::numeric_limits<unsigned int>::max()");
for (unsigned int pos{1}; pos<std::numeric_limits<decltype(mask)>::digits; ++pos ){
;//algorithm will be placed here, not implemented yet
}
return true;
}
int main()
{
unsigned int mask = 0b00110011;
auto result = has_holes<unsigned int>(mask); //works
auto result2 = has_holes(mask);//error: no matching function for call to 'has_holes(unsigned int&)'|
std::cout<<result<<" ..."<<result2<<std::endl;
return 0;
}
此致, 亨德里克
在 C++ 中,模板推导不是无限的。它将拒绝尝试反转可能的图灵完备过程。
C++ 标准将其称为非推导上下文:模板参数不会被推导的上下文。
remove_all_t<BASE_TYPE>
归纳出一个非推导的上下文。因为当您通过 remove_all_t<X>
等模板映射类型时,理论上 映射过程可能是图灵完备的。
一般来说,模板类型映射不会告诉 C++ 如何反转它们。该标准告诉编译器不要尝试。
删除 remove_all_t<BASE_TYPE>
并替换为 BASE_TYPE
,它将始终推导为一个值。
如果你害怕有人将 int&
作为模板类型参数显式传递,请在函数体中添加一个 static_assert( std::is_same<remove_all_t<BASE_TYPE>, BASE_TYPE>::value, "values only");
。
既然你关心的是位数,那么在算出位数的时候做类型缩减就好了。
template<typename BASE_TYPE,
class = typename std::enable_if_t<std::experimental::is_unsigned_v<remove_all_t<BASE_TYPE> > >
>
bool has_holes(BASE_TYPE mask)
{
using reduced_type = remove_all_t<BASE_TYPE>;
static_assert(std::numeric_limits<unsigned int>::max() > std::numeric_limits<reduced_type>::digits,
"Base_type has to many digits max_digits=std::numeric_limits<unsigned int>::max()");
for (unsigned int pos{1}; // really start at 1 (nor 0)?
pos < std::numeric_limits<reduced_type>::digits;
++pos )
{
//algorithm will be placed here, not implemented yet
}
return true;
}
尽管您可能不想接受 BASE_TYPE*
(所以必须修改它)。
模板参数推导已尝试,如[temp.deduct.call]/p1
中所述
P = typename remove_all<BASE_TYPE>::type
和 A = unsigned int
。最终 BASE_TYPE
无法推导(也无法默认),这变成了每个 [temp.deduct.type]/p2
.
作为旁注,我会使用一个简单的解决方法(因为您已经有其他静态断言)
template<typename BASE_TYPE, class = typename std::enable_if_t<std::experimental::is_unsigned_v<BASE_TYPE>, BASE_TYPE>,
typename RBASE_TYPE = remove_all_t<BASE_TYPE>>
^^^^^^^^^^
bool has_holes(BASE_TYPE mask){
// Use RBASE_TYPE here
return true;
}