重载函数以接受模板指针变量

时间:2013-04-02 02:30:26

标签: c++ templates pointers overloading

在main函数中调用push方法时使用。但是,即使main函数中的参数是指针,它仍然使用函数void Push(const DATA_TYPE& newValue)

不应该使用另一个,因为那是接受指针的人吗?如果存在指针变量,如何更改第二个函数中的参数以覆盖该参数?

template<typename DATA_TYPE>   
void Push(const DATA_TYPE& newValue)
{
    //do stuff
}

template<typename DATA_TYPE> 
void Push(const DATA_TYPE *newValue)
{
    //do stuff
}

3 个答案:

答案 0 :(得分:4)

你的问题在于constness。

问题在于,当您使用非const对象指针Push(p)调用P * p时,第一个版本在设置DATA_TYPE = P*时正好工作,给出{{1}的函数签名1}}。相比之下,DATA_TYPE = Push( const P* & )的第二个版本需要在类型签名中添加P才能获得const。这意味着选择第一个版本而不是第二个版本,因为它是精确匹配。

这是一个澄清正在发生的事情的例子:

以下是一个例子:

Push( const P* )

答案 1 :(得分:0)

我测试了这个程序

#include <iostream>

template <typename T>
void push(T&)
{
    std::cout << "By ref" << std::endl;
}

template <typename T>
void push(T*)
{
    std::cout << "By ptr" << std::endl;
}

int main()
{
    int x = 0;
    push(x);
    push(&x);
    return 0;
}

输出

By ref
By ptr

答案 2 :(得分:0)

这是因为const DATA_TYPE& newValue几乎可以匹配任何东西,在你的情况下它匹配作为指针const DATA_TYPE*& newValue的引用。尝试使用std::remove_pointer described here - 从我的头脑中我会写:

template<typename DATA_TYPE>   
void Push(const typename std::remove_pointer<DATA_TYPE>::type& newValue)
{
    //do stuff
}

template<typename DATA_TYPE> 
void Push(const DATA_TYPE *newValue)
{
    //do stuff
}

但是,编写匹配const T&模板以及其他模板重载的模板通常会导致const T&抓取每个调用,因此您应该避免以这种方式执行操作。

编辑:

我之前的代码不正确,它必须更复杂一些:

#include <iostream>
#include <type_traits>

template<typename DATA_TYPE, bool is_pointer>
struct helper;

template<typename DATA_TYPE>
struct helper<DATA_TYPE, true>{
    static void f(const typename std::remove_pointer<DATA_TYPE>::type*){
        std::cout << "Pointer" << std::endl;
    }
};

template<typename DATA_TYPE>
struct helper<DATA_TYPE, false>{
    static void f(const DATA_TYPE&){
        std::cout << "Non-pointer" << std::endl;
    }
};

template<typename DATA_TYPE>
void Push(const DATA_TYPE& newValue)
{
    helper<DATA_TYPE, std::is_pointer<DATA_TYPE>::value >::f(newValue);
}

int main()
{
    int i=0;
    Push(i);
    Push(&i);
    return 0;
}

这可以按预期工作,并且它不会强制调用者使用适当的常量,尽管我承认它不像我以前的解决方案那样迷人;)