2015-04-23 2 views
1

Я пытаюсь построить мини-тестовую структуру. У меня есть одна функция, которая принимает две переменные типа List, которые состоят из одного типа, и я планирую использовать параметры шаблона шаблона как часть интерфейса. До сих пор у меня есть это,Как указать общую переменную шаблона с двумя параметрами шаблона шаблона?

template <typename C, template <class> class A, template <class> class B> 
    static inline void assertEquals(const A<C>& expected, const B<C>& actual) { 
     auto success = 0, failure = 0; 

     for (auto iter1 = expected.cbegin(), iter2 = actual.cbegin(); 
      iter1 != expected.cend() && iter2 != actual.cend(); ++iter1, ++iter2) { 
     if (Test::assertEquals<C>(*iter1, *iter2)) { 
      ++success; 
     } else { 
      ++failure; 
     } 
     } 

     cout << "Success: " << success << endl 
      << "Failure: " << failure << endl; 
    } 

assertEquals в если условие другая функция. Мой вопрос: правильно ли интерфейс? Во-вторых, как я буду использовать его? Я попытался это не дало никаких результатов,

Test::assertEquals<int, std::vector, std::vector>(haystack, needle); 

Test:: просто класс, что функция находится в и haystack и needle имеют тип std::vector<int>.

+0

'станд :: вектор ' фактически 'станд :: вектор '. – Jarod42

+0

Вам действительно нужно предоставить 'C' в' Test :: assertEquals '? можно ли это вывести из аргументов? (если да, 'assertEquals (const T1 & expected, const T2 & actual)' достаточно). – Jarod42

+0

@ Jarod42 Право. Означает ли это, что я не могу инициализировать его как 'std :: vector '? Я думал, что, поскольку 'Alloc' является функцией' T', я могу просто включить 'T'. Это, по-видимому, ключевая проблема в том, что я делаю неправильно, поскольку @TartanLlama также указал – sguzman

ответ

3

Ваш интерфейс не принимает std::vector, так как он фактически принимает два аргумента шаблона: содержащийся тип и распределитель.

Вы можете изменить шаблон подписи принять VARIADIC шаблоны шаблонов, например:

template <typename C, template <class...> class A, template <class...> class B> 
static inline void assertEquals(const A<C>& expected, const B<C>& actual) { 

Или вы можете установить параметр по умолчанию в явном виде:

template <typename C, 
      template <class, class = std::allocator<C>> class A, 
      template <class, class = std::allocator<C>> class B> 
    void assertEquals(const A<C>& expected, const B<C>& actual) { 

Однако, вы, вероятно, лучше только получая C от типов элементов контейнера STL, например:

template <class A, class B> 
void assertEquals(const A& expected, const B& actual) { 
    static_assert(std::is_same<typename A::value_type, typename B::value_type>::value, 
        "Containers must have the same value type"); 
    using C = typename A::value_type; 
    //... 

Это гораздо более простой интерфейс. Для всех перечисленных выше опций, компилятор может вывести аргументы шаблона для вас, так просто называют это нравится:

assertEquals(haystack, needle); 
+0

Это тоже работает. Если бы мне захотелось перейти к шаблону параметра шаблона шаблона, это означало бы, что 'C' теперь является переменной пакета и использование его в параметрах функции будет выглядеть следующим образом:' ... const A & expected, ... '? – sguzman

+0

Нет, 'C' все еще один класс. Создание шаблона шаблона variadic по существу говорит компилятору принять любой шаблон шаблона, чтобы вы могли позволить использовать аргумент по умолчанию, не объявляя его явно. – TartanLlama

+0

Итак, как бы выглядело создание этого интерфейса? – sguzman