Мне нужно выбрать между двумя типами переменной во время компиляции. У одного из этих типов есть концептуальное требование, которое не всегда удовлетворяется, и именно тогда я хочу выбрать другой тип. Я пытаюсь добиться этого с помощью std::conditional_t, но оба типа std::conditional оцениваются, что приводит к сбою ограничения шаблона.
Вот минимальный пример:
#include <concepts>
template <typename T> requires std::same_as<T, int>
struct Foo {};
using MyType1 = std::conditional_t<true, int, Foo<int>>; // Compiles
using MyType2 = std::conditional_t<false, int, Foo<int>>; // Compiles
using MyType3 = std::conditional_t<true, int, Foo<double>>; // Doesn't compile (constraint fails)
using MyType4 = std::conditional_t<true, Foo<double>, int>; // Doesn't compile (constraint fails)
И MyType3, и 4 терпят неудачу, поскольку Foo не удовлетворяет ограничению Foo. Я ожидаю, что для MyType3 это сработает, поскольку в качестве типа условное условие выбирает int, а не Foo.
Могу ли я достичь своей цели с помощью std::conditional или любым другим способом?
Вы можете добавить некоторую косвенность:
template <template <typename> class C, typename T>
struct binder
{
using type = C<T>;
};
using MyType3 = std::conditional_t<true,
std::type_identity<int>,
binder<Foo, double>>::type;
Ответ Jarod42 хорош, но я также нашел другое возможное решение, используя специализацию шаблона, которую я публикую здесь для полноты картины:
#include <concepts>
template <std::same_as<int> T>
struct Foo {};
template <bool T>
struct MyConditional {
using type = int;
};
template <>
struct MyConditional<false> {
using type = Foo<int>;
};
using MyType3 = MyConditional<true>::type;
static_assert(std::is_same_v<MyType3, int>);
using MyType4 = MyConditional<false>::type;
static_assert(std::is_same_v<MyType4, Foo<int>>);
У вас больше нет Foo<double>
нигде ;-)
@Jarod42 Верно, но это решает общую проблему, когда мне нужен либо int, либо Foo<int> на основе значения истинности, что в моем реальном случае будет проверкой типа. Исходный минимальный пример построен не очень хорошо, поскольку Foo<double> немного искусственный.
Подсказка: концептуальную камеру можно включить в шаблон, например
template <std::same_as<int> T>
.