4

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
}
4

3 回答 3

4

你的问题在于常数。

问题是,当您Push(p)使用非常量对象指针调用时,P * p第一个版本在设置 DATA_TYPE= 时完全有效P*,函数签名为Push( const P* & ). 相比之下,带有 DATA_TYPE= 的第二个版本P需要const在类型签名中添加才能获取Push( const P* ). 这意味着选择第一个版本而不是第二个版本,因为它是完全匹配的。

这是一个示例来说明发生了什么:

这是一个例子:

#include <iostream>

class Foo
{
    public:
    template<typename DT>   
    void Push(const DT& newValue)
    {
        std::cout<<"In const DT& version"<<std::endl;
    }

    template<typename DT>
    void Push(const DT *newValue)
    {
        std::cout<<"In const DT* version"<<std::endl;
    }
};

int main()
{
    Foo f;

    int i=7;

    // Since i is not const we pickup the wrong version
    f.Push( i ); // const DT&  ( DT = int )
    f.Push( &i ); // const DT& ( DT = int* )

    // Here's using a const pointer to show it does the right things
    const int * const_i_ptr = &i;
    f.Push( const_i_ptr ); // const DT* ( DT = int );

    // Now using a const object everything behaves as expected
    const int i_const = 7;
    f.Push( i_const ); // const DT& ( DT = int );
    f.Push( &i_const ); // const DT*  (DT = int );
}
于 2013-04-02T02:40:23.610 回答
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
于 2013-04-02T02:36:51.187 回答
0

这是因为const DATA_TYPE& newValue它将匹配几乎任何东西,在你的情况下它匹配为对指针的引用const DATA_TYPE*& newValue。尝试使用std::remove_pointer 这里描述的 - 从我的头顶我会写:

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;
}

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

于 2013-04-02T02:42:46.777 回答