【问题标题】:How to recursively dereference pointer (C++03)?如何递归取消引用指针(C++03)?
【发布时间】:2011-11-05 19:48:48
【问题描述】:

我正在尝试递归地取消引用 C++ 中的指针。

如果传递的对象不是指针(这包括智能指针),我只想返回对象本身,如果可能的话通过引用。

我有这个代码:

template<typename T> static T &dereference(T &v) { return v; }
template<typename T> static const T &dereference(const T &v) { return v; }
template<typename T> static T &dereference(T *v) { return dereference(*v); }

我的代码在大多数情况下似乎都能正常工作,但它在给定函数指针时会中断,因为取消引用函数指针会导致函数指针类型完全相同,从而导致堆栈溢出。 p>

那么,当解引用的类型与原始对象的类型相同时,如何“停止”解引用过程?

注意:

我看到我的问题已被标记为与使用 Boost 的类似问题的重复;但是,我需要一个没有 Boost(或任何其他库)的解决方案。


例子:

template<typename T> T &dereference(T &v) { return v; }
template<typename T> const T &dereference(const T &v) { return v; }
template<typename T> T &dereference(T *v) { return dereference(*v); }

template<typename TCallback /* void(int) */>
void invoke(TCallback callback) { dereference(callback)(); }

void callback() { }

struct Callback {
     static void callback() { }
     void operator()() { }
};

int main() {
    Callback obj;
    invoke(Callback());          // Should work (and does)
    invoke(obj);                 // Should also work (and does)
    invoke(&obj);                // Should also work (and does)
    invoke(Callback::callback);  // Should also work (but doesn't)
    invoke(&Callback::callback); // Should also work (but doesn't)
    invoke(callback);            // Should also work (but doesn't)
    invoke(&callback);           // Should also work (but doesn't)
    return 0;
}

【问题讨论】:

  • 您能否具体说明您需要哪些编译器支持(C++98、C++03、C++11?)。
  • @fmaas:对不起,我对这有什么帮助有点困惑;你能详细说明一下吗?
  • 我很想知道是什么导致了反对票...
  • @Mehrdad 一个拥有超过 125 名声望的 SO 社区成员认为这个问题并不明确或有用......关于主题:这是来自 boost is_function.hpp @987654326 的一个很好的花絮@ 如果 MSVC9 处理得当,这可能有助于您寻求 SFINAE 触发器

标签: c++ templates pointers function-pointers visual-c++-2008


【解决方案1】:

根本没有依赖,简单,应该可以在 MSVC-2008 上运行。

template<typename T>
struct is_function
{
    static char     check(...);
    static double   check(const volatile void*); // function pointers are not convertible to void*
    static T        from;
    enum { value = sizeof(check(from)) != sizeof(char) };
};

template<bool, typename T = void>
struct enable_if{};

template<typename T>
struct enable_if<true, T>{typedef T type;};

template<typename T> 
T& dereference(T &v){return v;}

template<typename T> 
const T& dereference(const T& v){return v;}

template<typename T> 
typename enable_if<!is_function<T>::value, T&>::type dereference(T* v){return dereference(*v);}

【讨论】:

  • enable_iftype_traits 的一部分,你知道的。而且它仍然是 C++11。
  • 我知道 enable_if 是 C++11 中 type_traits 的一部分。但是,我必须自己定义它,因为 MSVC-2008 在 type_traits 中没有它。你是说这行不通吗?如果是这样,为什么不呢? SFINAE 也适用于 C++03。
  • TR1 由标准委员会作为技术报告 1 (ISO/IEC TR 19768) 发布。任何体面的编译器都可以实现它。没有理由不使用它。
  • @ronag:如果 TR1 是 C++ 标准,那么 C++11 将毫无意义。此外,您的回答仍然错过了问题的全部要点,即询问如何解决问题本身,而不是如何将其委托给其他地方。此外,对于可能与 C++11 及更高版本一起使用的代码,拥有 TR1 依赖项是不好的做法……更不用说在 TR1 之前出现的任何编译器(我猜这将是“不体面的”?)会窒息的。所以说真的,这根本不能回答问题。
  • 你的第一句话毫无意义。为什么拥有 TR1 依赖项是一种不好的做法,C++11 拥有 TR1 所拥有的一切。你的编译器有 TR1,如果你安装了 Service Pack 1,我不明白你为什么不这样做,因为它修复了错误?就我个人而言,我觉得你对想要帮助的人的态度相当不恰当,但也许我只是敏感。
猜你喜欢
  • 1970-01-01
  • 2019-05-20
  • 1970-01-01
  • 1970-01-01
  • 2010-12-04
  • 2013-12-11
  • 2011-06-17
  • 1970-01-01
  • 2014-05-10
相关资源
最近更新 更多