2017-01-02 4 views
11

У меня есть класс C с const и нефизических const добытчиками для некоторого общего типа Node:Функция возврата шаблон типа вычет

template <typename NodeType> 
class CParent{}; 

class Node {}; 

class C : public CParent<Node> { 
    Node&  getNode(Index i); 
    const Node& getNode(Index i) const; 
}; 

Теперь я хочу, чтобы создать функцию псевдонима, который называют getNode для объекта класса C :

template <class CType> 
NodeType& AliasGetNode(CType* cobject); 

Но как вывести NodeType? то есть, если я звоню AliasGetNode<const C>(c) и AliasGetNode<C>(c), NodeType должен быть соответственно const Node& и Node&.

Как это сделать?

Я пытался использовать result_of и decltype, но не был успешным.

+0

'Я попытался result_of и decltype подходы, но не successful.' Вы должны вывесить _what_ вы пробовали, и что случилось. Просто делать смутные намеки на вещи и говорить, что они не работают, не полезно.Я имею в виду, я предполагаю, что у вас только 49 ошибок шаблона, но было бы неплохо быть уверенным! –

+0

@underscore_d наверняка. Однако в этом случае, поскольку я ожидал, что решение будет простым, я попытался избежать 49 экранов беспорядка. Кроме того, есть много конкретных вопросов по теме «result_of» и «decltype», которые не затрагивают мою проблему, и я получаю неправильный «дублированный» флаг вопроса – manatttta

ответ

9

я рекомендовал бы:

template <class CType> 
auto AliasGetNode(CType& cobject) -> decltype(cobject.getNode(0)) 
{ 
    return cobject.getNode(0); 
} 

Это должно работать достаточно, так как C++ 11

+0

Выбрал это как ответ за не использование C++ 14, хотя это похоже на обходное решение – manatttta

+0

Почему не использует C++ 14 сделать это Правильнее? Если что-нибудь, это еще хуже, и вы ответили 'C++ 14' на свой вопрос. –

5

Определение простого вспомогательного признака, который будет добавлять/удалять const от типа на основе того, другой тип const:

template <class Src, class Dst> 
using copy_const = typename std::conditional< 
    std::is_const<Src>::value, 
    const Dst, 
    typename std::remove_const<Dst>::type 
>::type; 

И использовать его:

template <class CType> 
copy_const<CType, NodeType>& AliasGetNode(CType* cobject); 
17

Пусть компилятор выводит (с C++ 14):

template <class CType> 
decltype(auto) AliasGetNode(CType& cobject) 
{ 
    return cobject.getNode(0); 
} 
+4

Nice! в C++ 11 вы также можете сделать 'auto AliasGetNode (CType & cobject) -> decltype (cobject.getNode (0))' –

+0

@ W.F. Для C++ 14 вы имеете в виду. И возврат типа вывода на 'decltype (auto)' будет делать еще лучше :) – StoryTeller

+0

@StoryTeller Я действительно имею в виду для обоих стандартов :) –

3

Вы должны написать два псевдонима functi дополнения, один для неконстантного экземпляра, а другой для сопзЬ например:

template <class CType> 
const NodeType& AliasGetNode(const CType* cobject) const; // for const instance. 
// The function must be const since the only difference between return type will cause redefinition error. 

template <class CType> 
NodeType& AliasGetNode(CType* cobject); // for non-const instance 

Экземпляры объявлены сопзЬ будем называть константные функции, если есть функции перегрузки. Конечно, неконстантные экземпляры вызовут неконстантную версию функции перегрузки. Например:

class Aclass { 
    public: 
     string test() { return "calling non-const function"; } 
     string test() const { return "calling const function"; } 
}; 

int main() { 
    Aclass a; 
    const Aclass b; 

    cout << a.test() << endl; 
    cout << b.test() << endl; 

    return 0; 
} 

Результат будет:

calling non-const function 
calling const function 
4

Поскольку C++ 14 возвращаемый тип функции может быть выведен компилятором:

template<typename CType> 
decltype(auto) AliasGetNode(CType& cobject) { 
    return cobject.getNode(); 
} 

Когда вы звоните AliasGetNode на объекте типа Node, CType выведено на номер Node. Но если вы назовете AliasGetNode на объект типа const Node, то CType выводится на номер const Node.

Важно, чтобы тип возврата AliasGetNode был равен decltype(auto), иначе вы потеряете ссылку и константу для возвращаемого типа.

+1

'decltype (auto)' не гарантирует ссылочный тип возврата. 'auto &' и 'auto const &' do. – Potatoswatter

+0

@Potatoswatter, почему бы и нет? Вы можете объяснить? –

+0

См. Комментарий на ответ Майки :) – Potatoswatter

Смежные вопросы