Добавить специализацию к «заголовку» библиотеки с одним заголовком - PullRequest
0 голосов
/ 18 ноября 2018

В настоящее время работает над «библиотекой» с одним заголовком, включающей некоторый легкий TMP, который позволяет пользователям добавлять настройки / специализации для своих типов (как самообучающийся проект с реальным вариантом использования).

У меня проблемы с битом настройки.

Пример

// foo_library.h
void foo(int i) {}
void foo(bool b) {}

template<typename T>
void do_something(T t)
{
    foo(t);
}

// user_code.cpp: user adds specialisation for double
void foo(double d) {}

do_something(42);    // ok
do_something(false); // ok
do_something(3.14);  // error: do_something has not seen double overload

Примечание: речь идет о создании шаблона - я прекрасно знаю, что порядок («что-то видел») имеет значение в семействе C.

Зная, что создание экземпляра шаблона лениво, я предположил, что шаблон создан на месте, то есть увидел двойную специализацию. Очевидно, что это не так: (

Кажется, мне не хватает какой-то фундаментальной техники или концепции, потому что - это код , который позволяет пользователям "вставлять" свои настройки в библиотеки, содержащие только шаблоны, с заголовками (std::swap или nlohmann: : json приходит на ум)

Вопрос: Какой метод мне нужен, чтобы включить эту функцию внедрения настройки, просто попросив пользователя определить соответствующую функцию в некотором пространстве имен библиотеки?

Вещи, о которых я думал:

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

  • разделить заголовок на части, используя section-include-guards ( Symbolic C ++ делает это, хотя и не для настройки): потребует от пользователя подписки через макрос EVERY_CUSTOMIZATION_DEFINED_HERE или что-то подобное, не хочу этого.

  • обернуть вещи в шаблон класса, надеясь, что создание экземпляров ведет себя по-разному. Нет.

1 Ответ

0 голосов
/ 18 ноября 2018

Как указано в комментарии, для базовых типов ADL не существует, поэтому вы можете просто добавить фиктивный параметр (с зависимым именем):

template<typename> struct Tag{};

void foo(int i, Tag<int>) { std::cout << "int:" << i << std::endl;}
void foo(bool b, Tag<bool>) {std::cout << "bool:" << b << std::endl;}

template<typename T>
void do_something(T t)
{
    foo(t, Tag<T>{});
}

// user_code.cpp: пользователь добавляет специализацию для double

void foo(double d, Tag<double>) {std::cout << "double:" << d << std::endl;}
int main() {
    do_something(42);    // ok
    do_something(false); // ok
    do_something(3.14);  // use double overload :)
}

Демо

...