繁体   English   中英

模板函数参数列表中的常量被忽略

[英]Const being ignored in template function parameter list

我在模板类中的函数定义有问题。

我有一个模板类Array ,它具有成员函数IndexOf

// Defined in header
template <typename T>
class Array {
    // Other stuff

    int IndexOf(const T value) const {
        // Code of function
    };

    // Other stuff
};

当我使用类指针创建数组的实例时,该函数将忽略 const T并仅使用T 因此,当我使用const T调用函数时,会出现编译器错误:“无重载函数实例”:

#include "Array.h"

class Object{
    // Object stuff
};

int main(){
    // Demonstration code
    Array<Object*> objects = Array<Object*>(); // Array of Object*
    Object* obj = new Object();                // An Object*
    const Object* cobj = new Object();         // A const Object*

    // This works fine
    objects.IndexOf(obj); // No problems

    // This has compile error
    objects.IndexOf(cobj); // No idea why

    delete obj;
    delete cobj;

    return 0;
}

代码似乎忘记了函数的参数是const T 函数参数应为const Object* ,但它将参数视为仅Object*

知道为什么会这样吗?

如果我没有使用指针作为类型,则不会发生该错误。

函数内部的代码不会引起问题。

在不说之前,我不会使用std::vector或其他类似的东西来动态调整数组大小。 那会带走所有的乐趣。

实际上,您对函数的声明可以视为:

 IndexOf(const (Object *) val)

这基本上意味着Object *应该指向const对象,如下所示:

 Object *const cobj = new Object();

现在您将具有正确的行为。 但是,如果您真的对const指针感兴趣,则需要将声明修改为:

  Array<const Object *> objects;

const T value其中TObject*Object* const value constconst T value适用于value并不会修改T const T value是不能更改的T类型的value ,对于指针而言,这意味着无法分配新的地址。 显然,以下函数不能用const Object *调用。

int IndexOf(Object * const value) const // const pointer to non-const Object

要为指向类型添加const ,可以使用type-traits获取指向类型,向其添加const,然后从中生成新的指针类型。 例如 :

#include <type_traits>

template<class T>
using add_const_to_ptr =
    std::add_pointer_t<
    std::add_const_t<
    std::remove_pointer_t<T>>>;

其用法如下所示:

template<class T>
struct container {
    void push(add_const_to_ptr<T> ptr) {
        (void)ptr;
    }
};

struct bar {};

int main()
{
    const bar cbar;
    bar mbar;

    container<bar*> my_container;

    my_container.push(&mbar);
    my_container.push(&cbar);
}

尽管这假定container将仅与指针一起使用,在这种情况下,最好使T引用指向的对象类型,而不是指针类型。 如果T可能是或不是指针类型,则可以通过检查T是否实际上是带有std::conditional的指针来改进类型特征:

#include <type_traits>
template<class T>
using add_const_to_ptr =
std::conditional_t<std::is_pointer<T>::value,
    std::add_pointer_t<
    std::add_const_t<
    std::remove_pointer_t<T>>>,
    T>;

您可以将Array<Object*>::IndexOf()为模板:

template <typename U>
int IndexOf(const U& value) const {
    // Code of function
}

在内部,您将把value与数组的内容进行比较,并且这种比较会将内容从Object* const Object*const Object* ,这当然是允许的。

同样,使用这种方法,您可以将可以从T转换为/转换为T任何东西传递给该函数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM