Могу ли я использовать аргумент шаблона по умолчанию в прямой декларации

Итак, я пытаюсь понять, что происходит с реализацией Boost ptree.

В ptree.hpp фактически определяется basic_ptree:

template<class Key, class Data, class KeyCompare>
class basic_ptree

В ptree_fwd.hpp есть то, что выглядит как предварительное объявление basic_ptree, но с новым аргументом шаблона по умолчанию:

template < class Key, class Data, class KeyCompare = std::less<Key> >
class basic_ptree;

И, наконец, в ptree_fwd.hpp ptree равно typedef:

typedef basic_ptree<std::string, std::string> ptree;

Это предварительное объявление в ptree_fwd.hpp, верно? Итак, мне разрешено использовать аргумент шаблона по умолчанию в предварительном объявлении?


person Jonathan Mee    schedule 16.01.2018    source источник
comment
Вы можете объявить значение по умолчанию для параметра шаблона в объявлении шаблона точно так же, как вы можете объявить значение по умолчанию для параметра функции в объявлении функции.   -  person Sam Varshavchik    schedule 16.01.2018
comment
@SamVarshavchik Да, я знал это. Могу ли я использовать параметр шаблона по умолчанию в предварительном объявлении?   -  person Jonathan Mee    schedule 16.01.2018
comment
Это то, что я написал.   -  person Sam Varshavchik    schedule 16.01.2018
comment
@JonathanMee Вы можете сделать это как для объявлений (может быть несколько раз), так и для определения, и в конце концов они будут объединены; то же, что и аргументы функции.   -  person songyuanyao    schedule 16.01.2018
comment
@songyuanyao Похоже, вы говорите, что я могу указать аргумент по умолчанию в предварительном объявлении ... Что, я думаю, делает мое собственное предварительное объявление более запутанным. Мне бы очень хотелось, чтобы intellisense перешел к определению basic_ptree ptree.hpp, когда я нажимаю «Перейти к определению» моих локальных ptree, но я думаю, это объясняет, почему вместо этого он должен перейти к моему прямому определению.   -  person Jonathan Mee    schedule 16.01.2018
comment
@songyuanyao Они объединены, но вы можете указать значение по умолчанию для каждого параметра только один раз. Поскольку здесь мы говорим об одном значении по умолчанию, он не может указать его в обоих объявлениях.   -  person oisyn    schedule 16.01.2018
comment
@JonathanMee Целесообразно поместить аргументы по умолчанию в предварительное объявление, чтобы они были доступны при использовании шаблона в контекстах, где определение еще не известно. А затем убедитесь, что это предварительное объявление также известно во время определения.   -  person oisyn    schedule 16.01.2018
comment
@oisyn Я чувствую, что это очень быстро становится очень противным. Что, если я включу 2 отдельных заголовка, которые включают разные значения по умолчанию в свои предварительные объявления? Или это то, к чему вы обращаетесь?   -  person Jonathan Mee    schedule 16.01.2018
comment
@JonathanMee Я пишу ответ, через мгновение все станет ясно :)   -  person oisyn    schedule 16.01.2018


Ответы (1)


Да, ты можешь. Но вы можете указать каждый аргумент шаблона по умолчанию только один раз.

17.1/14

Набор аргументов шаблона по умолчанию, доступных для использования, получается путем слияния аргументов по умолчанию из всех предыдущих объявлений шаблона таким же образом, как и аргументы функции по умолчанию (dcl.fct.default).

[ Пример:

template<class T1, class T2 = int> class A;
template<class T1 = int, class T2> class A;

эквивалентно

template<class T1 = int, class T2 = int> class A;

— конечный пример ]

И 17.1/16

Параметр-шаблон не должен получать аргументы по умолчанию двумя разными объявлениями в одной и той же области. [ Пример:

template<class T = int> class X;
template<class T = int> class X { /* ... */ };  // error

— конечный пример ]

( Обратите внимание, что они взяты из последнего проекта, но, насколько мне известно, эти правила не менялись в последние годы )

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

Я чувствую, что это становится действительно неприятным очень быстро. Что, если я включу 2 отдельных заголовка, которые включают разные значения по умолчанию в свои предварительные объявления? Или это то, к чему вы обращаетесь?

Если бы вы сделали это, ваша программа была бы неправильно сформирована, поскольку вам разрешено указывать каждый аргумент по умолчанию только один раз. Наличие двух объявлений, одно из которых определяет аргументы по умолчанию, а другое — нет, на самом деле не вызывает никаких проблем, поскольку они не противоречат друг другу. Это означает только то, что если известна только версия без значений по умолчанию, вам нужно будет указать все аргументы при создании экземпляра шаблона.

Мое личное мнение состоит в том, чтобы иметь только одно объявление в заголовке, которое указывает аргументы шаблона по умолчанию, а затем включать этот заголовок везде, где вам нужно объявление (а также для определения).

person oisyn    schedule 16.01.2018
comment
Итак, что касается моих собственных форвардных объявлений, я явно больше не могу форвардно объявлять по умолчанию. Но тогда это не будет совпадать :( Должен ли я делать эту неприятную вещь в typedef, где я там по умолчанию, потому что тогда на самом деле использование моего кода ptree по умолчанию соответствует моему typedef, а не использует то, что определено в ptree_fwd.hpp, что, очевидно, имеет очень негативные последствия, если Boost что-то изменит. - person Jonathan Mee; 16.01.2018
comment
Итак, мой вопрос изначально состоял из двух вопросов, объединенных в один. Я упростил этот вопрос, сделав его более полным ответом. Но я также выделил другую половину вопроса в отдельный вопрос. Если вы так склонны, я был бы признателен за некоторые указания и здесь: stackoverflow.com/q/48302501/2642059 - person Jonathan Mee; 17.01.2018