2015-07-24 2 views
0

Я следующую структуру класса, который пытается создать время компиляции, сгенерированные иерархического дереваНе удается вывести параметр шаблона

struct NodeBase{ 
    virtual constexpr uint32_t size() const = 0; 
    virtual constexpr bool empty() const = 0; 
    constexpr NodeBase(){}; 
}; 

template <size_t L> 
class Node : NodeBase{ 
private: 
    const uint32_t * const ptr; 
    const std::array<const NodeBase &, L> nodes; 

public: 
    constexp Node(std::initializer_list<NodeBase> const ts, uint32_t const * const ptr) : 
     NodeBase(), 
     ptr(ptr), 
     nodes{ts} 
     { 
     }; 
    constexpr uint32_t size() const { 
     return nodes.size(); 
    } 
    constexpr bool empty() const { 
     return (ptr==nullptr) ? true : false; 
    } 
} 

// helper function should allow for template deduction 
template<size_t T> 
constexpr Node<T> makeNode(std::initializer_list<NodeBase> const ts, uint32_t const * const ptr){ 
    return Node<T>(ts, ptr); 
}; 

template <size_t L> 
class Item : Node{ 
public: 
    constexpr Item() : 
     Node<L>({member}, nullptr) 
    { 
    }; 
private : 
    // here lies the problem 
    template <size_t M> 
    static constexpr Node<M> member = makeNode({},nullptr); 
} 

Однако это дает компилятор (GCC 4.9.1) ошибка: нет соответствия вызов функции makeNode (, null_ptr_t) и примечание, чтобы сказать, что не удалось вывести тип шаблона.

Я могу исправить ошибку, перемещая параметр M в шаблон уровня класса, но это имеет некоторые довольно ужасные последствия, поскольку список параметров будет расти на каждом уровне иерархии дерева. Я уверен, что компилятор должен иметь возможность выводить тип, который зависит от длины списка инициализации, предоставленного конструктору. Есть предположения?

+0

Это переменный шаблон? Если да, не следует ли этому вопросу отмечать C++ 14, а не C++ 11? Кроме того, конструктор узла объявлен constexpr, но функция 'makeNode' не является, поэтому я не думаю, что член может быть создан во время компиляции так, как сейчас. – JorenHeit

+0

Я пробовал это с contexpr на makeNode, без изменений – OllieB

+0

JorenHeit: C++ - это C++ 14. нет необходимости отмечать его 14 или 11. –

ответ

1

Основываясь на ваш комментарий, я думаю, что это то, что вам может понадобиться. Я отказался от использования std::initializer_list. В C++ 14 он должен иметь член constexpr, чтобы возвращать количество элементов, но я не мог заставить это работать, и вы помечали свой вопрос C++ 11 в любом случае. Вместо этого я использую простой старый массив C, размер которого можно вывести с помощью механизма шаблона.

template <size_t M> 
struct Node {}; 

template <size_t M> 
constexpr Node<M> makeNode(int const (&list)[M]) 
{ 
    return Node<M>(); 
} 

class Item 
{ 
    static constexpr auto member = makeNode({1, 2, 3}); 
}; 

Обратите внимание, что использование auto в области видимости класса работает только для статических членов, но вы, кажется, отвечают этому требованию.

3

Как компилятор должен выводить тип шаблона, если в параметрах функции нет использования типа шаблона? Может быть, вы хотите

static constexpr Node<M> member = makeNode<M>({},nullptr); 
+0

Проблема с использованием L заключается в том, что массив дочерних кодов на каждом уровне иерархии тогда должен быть такой же длины, что нежелательно. – OllieB

+0

Я мог бы вручную определить длину (0,1,2 и т. Д.), Но я надеялся на что-то более общее. – OllieB

+0

Вместо этого вы можете использовать 'std :: array ', что должно сделать вывод (непроверенный). – TartanLlama

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