2015-01-16 2 views
1

В следующем коде:Как решить эту двусмысленность?

template <int...> struct IndexSequence {}; 

template <int, int, typename, int...> struct Helper; 

template <int Start, typename Coefficients, int... Is> 
struct Helper<Start, Start, Coefficients, Is...> { 
    using type = IndexSequence<Is...>; 
}; 

template <int Start, int N, int... As, int... Is> 
struct Helper<Start, N, IndexSequence<As...>, Is...> : 
    Helper<Start, N-1, IndexSequence<As...>, N-1, Is...> {}; 

int main() { 
    Helper<2,5, IndexSequence<1,2,3>>::type a; 
} 

я получаю ошибку компиляции:

ambiguous class template instantiation for 'struct Helper<2, 2, IndexSequence<1, 2, 3>, 2, 3, 4>'

Я полагал, что это разрешило бы к специализации

template <int Start, typename Coefficients, int... Is> 
struct Helper<Start, Start, Coefficients, Is...> { 
    using type = IndexSequence<Is...>; 
}; 

Но я предполагаю, что это также чтение

struct Helper<Start, N, IndexSequence<As...>, Is...> : 
    Helper<Start, N-1, IndexSequence<As...>, N-1, Is...> {}; 

Как решить эту двусмысленность?

+0

Как использовать код библиотеки? http://en.cppreference.com/w/cpp/utility/integer_sequence –

+0

Ну, вы можете сказать по имени «Коэффициенты», что я пытаюсь обобщить std :: integer_sequence, указав полином с коэффициентами, указанными 'As ... '. Я уже написал и протестировал 'PolynomialValue :: value' в моей программе, чтобы сделать это (чтобы заменить второй« N-1 »в приведенном выше коде. У меня просто проблемы с указанной двусмысленностью. – prestokeys

ответ

3

Проблема в том, что ни одна из специализаций не является более специализированной, чем другая.

При принятии решения о том, какая частичная специализация также выбирается, специализации сначала сопоставляются с аргументами, чтобы проверить, являются ли они жизнеспособными (здесь оба они). Если несколько из них жизнеспособны, то чтобы решить, какой из них нужно выбрать, мы должны проверить, какая из них более специализирована, чем все остальные. Этот процесс называется «частичным упорядочением» и выполняется путем сравнения специализированных шаблонов «аргументы», которые друг с другом (т. Е. Аргументы шаблона в Helper<...>) - в качестве шаблона аргумента принимается один шаблон, а другой - шаблон параметра. Шаблон аргумента предоставляет типы, и выполняется вывод, чтобы проверить, можно ли выводить параметры шаблона из шаблона параметра с учетом типов шаблона аргумента.

template <int Start, typename Coefficients, int... Is> 
struct Helper<Start, Start, Coefficients, Is...> 
//   ^^^^^ ^^^^^ ^^^^^^^^^^^^ ^^^^^ 
// A:   1  2   3   4 

template <int Start, int N, int... As, int... Is> 
struct Helper<Start, N, IndexSequence<As...>, Is...> 
//   ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^ 
// B:   1 2   3    4 

Для каждого аргумента шаблона аргумента, некоторые уникальное значение состоит для каждого параметра шаблона и замещенный в аргумент. Затем эти преобразованные аргументы передаются в шаблон параметров, чтобы проверить, не удастся ли выполнить вывод или не удалось. В качестве примера:

  • A1 выведено против B1, что преуспевает. (int может быть выведено из int)
  • B1 выведен на A1, ... как указано выше. Работает отлично.

Давайте теперь посмотрим на важнейших выводов:

  • В2 выведенные против А2, но, как мы использовали уникальные значения для обоих Start и N, Start в шаблоне А выведенные непоследовательно, который означает, что удержание здесь не выполняется.

  • A3 выведено против B3, но поскольку Coefficients - это уникальный тип (не специализация IndexSequence!), То вычет снова невозможен.

Вычет не удался, по крайней мере один раз в оба направления: Таким образом, ни шаблон не в полном объеме более специализирован, чем другие.


Решите эту двусмысленность частичного заказа, например.написав первую специализацию как

template <int Start, int... As, int... Is> 
struct Helper<Start, Start, IndexSequence<As...>, Is...> { 
    using type = IndexSequence<Is...>; 
}; 

Теперь второй вывод, вышедший не выше, больше не подлежит. Только тот, который взял специализацию B в качестве шаблона аргумента. Это означает, что B более специализирован и выбран таким образом.

Demo.

+0

Ну, я понять, что компилятор был смущен, о какой специализации использовать. – prestokeys

+0

Примечание: я могу подробно рассказать о том, как устанавливаются шаблоны функций, используемые для частичного упорядочения, и как вычет затем описывается в [temp.educt .type]/9 и т. д. На данный момент это довольно сокращено. – Columbo

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