3

首先,我不明白为什么编译器似乎无法解析有问题的代码(由 ENABLE_OFFENDER 宏包装)。这两个 get() 方法具有非常不同的调用签名。所以,也许 C++ 语言律师可以帮助解释我为什么会收到错误。

其次,有没有办法为编译器提供更多关于它应该使用哪个 get() 的指导?

#include <iostream>

//switch offending code in/out
#define ENABLE_OFFENDER

/// Forward declare
template <typename T> class TableEntry;

/// Non-template base class
class TableEntryBase {
protected:
    // prevent instantiation
    TableEntryBase() { }
public:
    virtual ~TableEntryBase() { }

    template <typename T>
    void set(const T& rvalue){
        TableEntry<T>* entry = dynamic_cast<TableEntry<T> *>(this);
        if(0 != entry){
            entry->setValue(rvalue);
        }
    }

    template <typename T>
    T get(T& lvalue){
        TableEntry<T>* entry = dynamic_cast<TableEntry<T> *>(this);
        if(0 != entry){
            return entry->getValue(lvalue);
        } else {
            return T();
        }
    }

    template <typename T>
    T get(){
        TableEntry<T>* entry = dynamic_cast<TableEntry<T> *>(this);
        if(0 != entry){
            return entry->getValue();
        } else {
            return T();
        }
    }

};

template <typename T>
class TableEntry : public TableEntryBase {
private:
    T m_value;
public:
    TableEntry():TableEntryBase() { }
    ~TableEntry() { }
    void setValue(const T& rvalue){
        m_value = rvalue;
    }
    T getValue(T& lvalue){
        lvalue = m_value;
        return m_value;
    }
    T getValue(){
        return m_value;
    }
};


template <int N>
class Table {
private:
    TableEntryBase* m_tableEntries[N];
    int m_tableEntriesIndex;
public:
    Table():m_tableEntriesIndex(0){}

    virtual ~Table() { }

    void addEntry(TableEntryBase* entry){
        if(0 != entry)
            m_tableEntries[m_tableEntriesIndex++] = entry;
    }

    template <typename T>
    void setEntry(int entryIndex, const T& rvalue){
        // I'm not sure why it's not set<T>(rvalue)
        m_tableEntries[entryIndex]->set(rvalue);
    }

    template <typename T>
    T getEntry(int entryIndex, T& lvalue){
        return m_tableEntries[entryIndex]->get(lvalue);
    }

#ifdef ENABLE_OFFENDER
    template <typename T>
    T getEntry(int entryIndex){
        return m_tableEntries[entryIndex]->get();
    }
#endif
};


int main(){
    TableEntry<int> entry1;
    // setting the value using base class set
    entry1.set<int>(5);

    TableEntry<double> entry2;
    entry2.set<double>(3.14);

    std::cout << "entry1 value = " << entry1.getValue() << std::endl;
    std::cout << "entry2 value = " << entry2.getValue() << std::endl;

    std::cout << "entry1 value = " << entry1.get<int>() << std::endl;
    std::cout << "entry2 value = " << entry2.get<double>() << std::endl;
    TableEntryBase* entry_ptr = &entry1;
    std::cout << "entry1 value = " << entry_ptr->get<int>() << std::endl;

    Table<2> table;
    table.addEntry(&entry1);
    table.addEntry(&entry2);
    table.setEntry<int>(0, 10);
    std::cout << "entry1 value = " << entry1.get<int>() << std::endl;
    std::cout << "entry2 value = " << entry2.get<double>() << std::endl;
    int val3 = 0;
    int val4 = 0;
    val4 = table.getEntry<int>(0, val3);
    int val5 = 0;
#ifdef ENABLE_OFFENDER
    val5 = table.getEntry<int>(0);
#endif
    std::cout << "val3 = " << val3 << ", val4 = " << val4 << ", val5 = " << val5 << std::endl;
    return 0;
}

/* GCC error
main.cpp:129:30:   instantiated from here
main.cpp:96:95: error: no matching function for call to ‘TableEntryBase::get()’
main.cpp:96:95: note: candidates are:
main.cpp:26:4: note: template<class T> T TableEntryBase::get(T&)
main.cpp:36:4: note: template<class T> T TableEntryBase::get()
*/

通过更改有问题的代码,我让代码在我的旧编译器上工作。

#ifdef ENABLE_OFFENDER
    template <typename T>
    T getEntry(int entryIndex){
        // Error: expected primary-expression before ‘&gt;’ token
        //return m_tableEntries[entryIndex]->get<T>();

        // Error: couldn't deduce template parameter ‘T’
        //return m_tableEntries[entryIndex]->get();

        TableEntryBase* entry = m_tableEntries[entryIndex];
        return entry->get<T>();
    }
#endif
4

0 回答 0