Частичное упорядочивание вариабельных шаблонных функций

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

template <const char *str1, const char*... str2> 
struct restrictedValues
{
...
};

Чтобы проверить эту новую опцию, вы должны перегрузить boost::program_options::validate функция:

template<class T, class charT>                                                                            
void validate(boost::any& v, const std::vector< std::basic_string<charT> >& xs, T*, long);

Вызов для этой функции проверки следующий:

validate(value_store, new_tokens, (T*)0, 0);

Как уточняется в boost: "Тип цели указывается с помощью параметра, который имеет тип указателя на нужный тип. Это обходной путь для компиляторов без частичного упорядочивания шаблонов, как и в последнем параметре long / int".

Я, следовательно, написал свою проверочную версию следующим образом:

template<class charT, const char *... str>
void validate(boost::any &v,
        const std::vector<std::basic_string<charT> >& values,
        restrictedValues<str...>* /*target_type*/,
        int /*unused*/) { ... }

Похоже, что моя версия clang (версия 3.5.0-4ubuntu2 ~ Ubuntu clang ~trusty2 (tags/RELEASE_350/final) (основанная на LLVM 3.5.0)) просто пропускает мою версию и терпит неудачу в версии по умолчанию. Пока мой gcc ((Ubuntu 4.8.2-19ubuntu1) 4.8.2) успешно компилируется.

РЕДАКТИРОВАТЬ См живой пример, который показывает другое поведение, кредиты @dyp:

Жить на Колиру

#include <boost/any.hpp>
#include <vector>
#include <string>
#include <iostream>

template <const char *str1, const char*... str2> struct restrictedValues                                                                                
{
/*...*/
};

template<class T, class charT>                                                                            
void validate(boost::any&, const std::vector< std::basic_string<charT> >&, T*, long)
{
    std::cout << "default version\n";
}

extern char const client[] = "hello";
extern char const server[] = "world";

template<class charT, const char *... str>
void validate(boost::any &,
        const std::vector<std::basic_string<charT> >&,
        restrictedValues<str...>* /*target_type*/,
        int /*unused*/) {
    std::cout << "custom version\n";
}

int main()
{
    boost::any a;
    std::vector<std::string> xs;
    restrictedValues<client, server>* p = 0;
    validate(a, xs, p, 0);
}

Более того, тот же процесс, использующий невариантные шаблоны (фиксированное число const char*) для структуры / функции, работает как шарм.

Я не совсем уверен, какой процесс поиска приводит к такой неоднозначной ошибке. Если бы моя функция не использовала шаблон, он был бы выбран в соответствии с правилами перегрузки, но это не так. Читая правила частичного упорядочения для шаблонных функций, обе функции имеют одинаковую специализацию для параметров шаблона, но я ожидаю, что трюк int/long должен работать. Любая идея о том, как решить эту загадку шаблона?

1 ответ

Обычный подход здесь состоит в том, чтобы заставить ADL работать, используя сильные typedefs.

Я задокументировал это в более старом ответе:


Comments первые комментарии там устарели и ссылаются на старый ответ, который я имел раньше.

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