Главный технологический недостаток MethodB, который я видел, заключается в том, что при применении к нему универсального кода мы должны удвоить код для обработки как константной, так и неконстантной версии. Например:
Допустим, T является упорядоченным объектом (т. Е. Мы можем сравнивать объекты типа T с оператором
Для метода A все, что нам нужно для кодирования:
template <typename T>
T & getMax(T & p_oLeft, T & p_oRight)
{
if(p_oLeft.get() > p_oRight.get())
{
return p_oLeft ;
}
else
{
return p_oRight ;
}
}
Этот код будет работать как с константными объектами, так и с неконстантными объектами типа T:
// Ok
const MethodA oA_C0(), oA_C1() ;
const MethodA & oA_CResult = getMax(oA_C0, oA_C1) ;
// Ok again
MethodA oA_0(), oA_1() ;
MethodA & oA_Result = getMax(oA_0, oA_1) ;
Проблема возникает, когда мы хотим применить этот простой код к чему-либо, следуя соглашению MethodB:
// NOT Ok
const MethodB oB_C0(), oB_C1() ;
const MethodB & oB_CResult = getMax(oB_C0, oB_C1) ; // Won't compile
// Ok
MethodA oB_0(), oB_1() ;
MethodA & oB_Result = getMax(oB_0, oB_1) ;
Чтобы MethodB работал как с константной, так и с неконстантной версией, мы должны оба использовать уже определенный getMax, но добавить к нему следующую версию getMax:
template <typename T>
const T & getMax(const T & p_oLeft, const T & p_oRight)
{
if(p_oLeft.getAsConst() > p_oRight.getAsConst())
{
return p_oLeft ;
}
else
{
return p_oRight ;
}
}
Заключение. Не доверяя компилятору использование констант, мы обременяем себя созданием двух универсальных функций, когда одной должно быть достаточно.
Конечно, при достаточной паранойе, вторая функция шаблона должна была называться getMaxAsConst ... И, таким образом, проблема распространялась бы по всему коду ...
: - р