Параметры шаблона, для которых требуется выводимый аргумент * перед * пользовательскими аргументами - PullRequest
0 голосов
/ 29 января 2019

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

template <typename T, T N>
class int_const {};

template <typename T, T M, T N>
auto add(int_const<T, N> a) {
    return int_const<T, N + M>();
}

int main(void) {
    int_const<int, 1> a;
    add<32>(a); 
    // add<int, 32>(a); does compile, but requires the user to know or extract that first argument
    return 0;
}

Есть ли в любом случае поддержка вызова функции шаблона, как это видно в main()?

1 Ответ

0 голосов
/ 29 января 2019

Если вы можете использовать C ++ 17, вы можете использовать auto для M значение

template <auto M, typename T, T N>
auto add(int_const<T, N> a) {
    return int_const<T, N + M>();
}

Таким образом, вы можете назвать его следующим образом

add<32>(a);

До C++ 17 ... ну, я не вижу пути без объяснения также типа.

Как указывает Jarod42, auto M перехватывает также значения разных типов.

Если выхотите навязать, что тип M равен точно T, вы можете использовать SFINAE;Например, следующим образом:

template <auto M, typename T, T N, 
          std::enable_if_t<std::is_same_v<T, decltype(M)>, bool> = true>
auto add(int_const<T, N> a) {
    return int_const<T, N + M>();
}

Таким образом, вы получаете ошибки от

add<32u>(a);
add<short{32}>(a);

Но, возможно, вы можете ослабить требование и принять также, что decltype(M) не совсем T, нотакже просто, что M сужается, преобразуется в T.

Возможно

template <auto M, typename T, T N>
auto add(int_const<T, N> a) {
    return int_const<T, N + T{M}>();
} // .......................^^^^

, поэтому

add<32u>(a);
add<short{32}>(a);

скомпилированы, потому что 32u и short{32}конвертируемо в int, где

add<(unsigned long)(-1)>(a);

дает ошибку компиляции, потому что (unsigned long)(-1) (обычно большее возможное значение для unsigned long) не может быть сужено до int.

...