Nem*_*ric 1 c++ templates pointers enable-if c++11
在尝试回答这里的一个问题时,我发现了这个问题:
答案的改编代码如下:
template<typename T> T& dereference(T &v) { return v; }
template<typename T> const T& dereference(const T &v) { return v; }
template <typename T>
typename std::enable_if<!std::is_pointer<T>::value, T&>::type
dereference(T *v) {
return dereference(*v);
}
Run Code Online (Sandbox Code Playgroud)
但是,在此测试中,无法将指针指向取消引用到值类型:
template <typename T>
class A
{
public:
bool compare(T a, T b){
return dereference(a) < dereference(b);
}
};
int main()
{
int u = 10;
int *v = &u;
int **w = &v;
int i = 5;
int *j = &i;
int **k = &j;
A<int> a;
A<int*> b;
A<int**> c;
std::cout << a.compare(i, u) << std::endl;
std::cout << b.compare(j, v) << std::endl;
// This fails - 5 < 10 == 0
std::cout << **k << " < " << **w << " == " << c.compare(k, w) << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
显然,w并且k只有一次derefenced,这导致operator<被调用两个指针.
我可以通过添加以下内容来解决此问题:
template <typename T>
typename std::enable_if<!std::is_pointer<T>::value, T&>::type
dereference(T **v) {
return dereference(*v);
}
Run Code Online (Sandbox Code Playgroud)
但是它会失败的int***.
有没有办法在不手动添加级别的情况下递归递增?
注意这只是"理论上的"问题.
这可以通过使用自定义can_dereference特征来实现:
template <typename T>
struct can_dereference_helper {
template <typename U, typename = decltype(*std::declval<U>())>
static std::true_type test(U);
template <typename...U>
static std::false_type test(U...);
using type = decltype(test(std::declval<T>()));
};
template <typename T>
struct can_dereference :
can_dereference_helper<typename std::decay<T>::type>::type {};
Run Code Online (Sandbox Code Playgroud)
以及一些带有bit'o标签调度的互相递归函数:
template <typename T>
auto recursive_dereference(T&& t, std::false_type) ->
decltype(std::forward<T>(t)) {
return std::forward<T>(t);
}
template <typename T>
auto recursive_dereference(T&& t) ->
decltype(recursive_dereference(std::forward<T>(t), can_dereference<T>{}));
template <typename T>
auto recursive_dereference(T&& t, std::true_type) ->
decltype(recursive_dereference(*std::forward<T>(t))) {
return recursive_dereference(*std::forward<T>(t));
}
template <typename T>
auto recursive_dereference(T&& t) ->
decltype(recursive_dereference(std::forward<T>(t), can_dereference<T>{})) {
return recursive_dereference(std::forward<T>(t), can_dereference<T>{});
}
Run Code Online (Sandbox Code Playgroud)
看它在Coliru现场工作.与Kerrek的回答相比,这似乎有些过分,但我选择了一种通用的方法来取消任何支持的方法operator*.我会让你决定哪种工具最适合你的问题.
| 归档时间: |
|
| 查看次数: |
391 次 |
| 最近记录: |