Параметры шаблона шаблона и аргументы по умолчанию

Рассмотрим следующий код, который использует параметры "шаблон шаблона" для создания шаблона класса с использованием нескольких типов:

#include <iostream>
using namespace std;

enum E
{
    a = 0,
    b = 1
};

template <template <E> class Action, class T>
void do_something(const T& value)
{
    typedef Action<a> type1;
    typedef Action<b> type2;
}

template <E e, class Enable = void>
class Foo
{

};

int main()
{
    do_something<Foo>(int(55));
}

Используя более старый компилятор (GCC 4.1.2), приведенный выше код прекрасно компилируется. Однако при использовании более нового компилятора (GCC 4.4.6 или 4.8.1) выдается следующая ошибка:

test3.cpp:25:27: error: no matching function for call to ‘do_something(int)’
  do_something<Foo>(int(55));

Похоже, что GCC не может связываться с do_somethingпотому что параметры шаблона шаблона объявляют только один параметр (перечисление), но Foo фактически принимает два параметра шаблона (даже если один является значением по умолчанию.) Я думаю, что GCC 4.1.2 допускает игнорирование параметра по умолчанию.

Хорошо, если я изменю определение шаблона на:

template <template <E, class> class Action, class T>
void do_something(const T& value)
{
    typedef Action<a> type1;
    typedef Action<b> type2;
}

... тогда ни одна версия GCC, которую я тестировал, не скомпилирует ее. Все они выдают похожую ошибку:

test3.cpp:13: error: wrong number of template arguments (1, should be 2)
test3.cpp:10: error: provided for ‘template<E <anonymous>, class> class Action’

Так что теперь компилятор жалуется, потому что выражение typedef Action<a> type1 предоставляет только один параметр шаблона. По-видимому, я не могу неявно использовать параметр по умолчанию здесь.

Есть ли способ использовать параметр шаблона по умолчанию в функции шаблона шаблона?

2 ответа

Решение

Аргументы по умолчанию игнорируются для параметров аргументов шаблона. Этот пример есть в n3337, глава [temp.arg.template], пункт 2:

template<class T> class A { /∗ ... ∗/ };
template<class T, class U = T> class B { /∗ ... ∗/ };
template <class ... Types> class C { /∗ ... ∗/ };
template<template<class> class P> class X { /∗ ... ∗/ };
template<template<class ...> class Q> class Y { /∗ ... ∗/ };
X<A> xa; // OK
X<B> xb; // ill-formed: default arguments for the parameters of a template argument are ignored
X<C> xc; // ill-formed: a template parameter pack does not match a template parameter
Y<A> ya; // OK
Y<B> yb; // OK
Y<C> yc; // OK

Обратите внимание на комментарий на X<B> xb; выше. Боюсь, я не могу найти нормативный текст.

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

С using Псевдоним шаблона, новая функция в C++11, вы можете создать шаблон с одним параметром, который эквивалентен другому шаблону, который имеет два параметра, один из которых по умолчанию.

template <E e> using Foo1 = Foo<e>;

Это создает Foo1шаблон с одним параметром, хотя Foo технически имеет два аргумента, один из которых по умолчанию. Вы можете использовать его как:

do_something<Foo1>(int(55));

В качестве альтернативы, если C++ 11 такие функции, как using недоступны, тогда вы сканируете указать значение по умолчанию в вашем объявлении do_something, Это значит, к сожалению, что do_something больше не может иметь дело с простыми шаблонами с одним аргументом. Следовательно, я думаю, что using выше метод лучше.

template <template <E, class = void> class Action, class T>
void do_something(const T& value);

Если вы воспользуетесь этим подходом, поместите значение по умолчанию в аргументы do_something, тогда это значение по умолчанию имеет приоритет над значением по умолчанию, указанным в объявлении Foo, Это основано на моих экспериментах, и я не могу с уверенностью комментировать то, что является и не является стандартом. Но я думаю, что using Трюк полностью соответствует стандартам в отношении C++ 11.

(Ubuntu Clang версии 3.0-6ubuntu3)

Другие вопросы по тегам