簡體   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