如何递归取消引用指针(C++03)?

13
我正在尝试在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); }

我的代码在大多数情况下似乎都能正常工作,但是当给定函数指针时会出现问题,因为对函数指针进行解引用会导致与原始类型相同的函数指针,从而导致堆栈溢出。
那么,当解引用类型与原始对象具有相同类型时,我该如何“停止”解引用过程呢?
注意:
我看到我的问题已被标记为使用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;
}

3
可能是与函数指针上的函数模板特化重复的问题。 - Lightness Races in Orbit
1
你能具体说明你需要哪种编译器支持吗?(C++98,C++03,C++11?) - sehe
在我看来,避免使用boost确实相当复杂。特别是如果你涉及到严肃的模板元编程。不过,真正热衷于此的人,也许不介意从头开始编写boost :) - sehe
@sehe:当然,如果我能够从头开始学习如何编写Boost库,那么也许我不会介意。但是为了学习它,我仍然需要先学习没有Boost的内容,否则这样做就有点失去了意义... - user541686
@fmaas:提供了一个例子;感谢您的建议。 - user541686
显示剩余4条评论
1个回答

6

没有任何依赖关系,简单易用,应该可以在 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);}

1
enable_iftype_traits 的一部分,你知道的。而且它仍然是 C++11。 - Cat Plus Plus
我知道在C++11中,enable_if是type_traits的一部分。然而,由于MSVC-2008在type_traits中没有它,我必须自己定义它。你是说这样行不通吗?如果是这样,为什么?SFINAE在C++03中也可以工作。 - ronag
TR1是由标准委员会发布的技术报告1(ISO/IEC TR 19768)。任何一个体面的编译器都会实现它。没有理由不使用它。 - ronag
@ronag:抱歉我有点烦躁,因为你在做出“我不明白你为什么不这样做”和“没有理由不使用它”的断言,然而实际上完全忽略了问题的前提,即特别针对C++11相关功能(以及Boost或类似功能)不存在的情况,这一点我认为已经表达得非常清楚了。感谢你的帮助,但是答案并没有回答问题,尽管在其他情况下可能很有帮助。:( - user541686
如果你没有它,那么函数调用将会是模糊的,编译器就不会知道该选择哪一个。 - ronag
显示剩余8条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接