首先,我不明白为什么编译器似乎无法解析有问题的代码(由 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 ‘>’ 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