Руководящее объявление для оператора шаблонного преобразования

Рассмотрим что-нибудь вроде следующего:

template <typename T> struct Foo;

template <typename S> struct Bar
{
template <typename T> operator Foo<T>();

// ...
};

class Baz
{
Baz(Foo<int>&);
};

int main()
{
Bar<float> bar;
Baz        baz(bar); // Won't work
}

Я хотел бы использовать шаблонный оператор, чтобы указать серию возможных преобразований, чтобы избежать дублирования кода / копирования и вставки. Однако, конечно, теперь ряд преобразований, как в закомментированной строке кода, не будет работать, потому что в C ++ разумный компилятор не будет рассматривать все формы шаблонных операторов, поскольку это было бы неразрешимо.

Если я вместо этого выберу вырезать и вставить, и определить Бар следующим образом:

template <typename S> struct Bar
{
operator Foo<int>();
operator Foo<float>();
// many more

// ...
};

Теперь цепное преобразование можно определить и найти. Я хотел бы иметь возможность иметь свой торт и есть его, в частности определить оператор как шаблон, но также предоставить серию направляющих объявлений, которые можно использовать так, как если бы операторы преобразования были определены как не-шаблоны:

template <typename S> struct Bar
{
template <typename T> operator Foo<T>();

template operator Foo<int>(); // Not valid C++
template operator Foo<float>(); // Not valid C++
// ...
};

Есть ли способ сделать это в C ++ 11 / C ++ 14? Есть ли у кого-нибудь предложения по структурированию кода, которые позволили бы не иметь репликации определения оператора преобразования, но при этом иметь конечный набор экземпляров оператора преобразования, которые будут использоваться, как если бы они были определены индивидуально?

1

Решение

Ваша проблема не в декларации вашего оператора преобразования, это ваша Baz конструктор:

Baz(Foo<int>&);

Это принимает неконстантную ссылку на Foo<int>, Когда вы неявно конвертируете Bar<S> к Foo<T>, вы создаете временный объект, который не может быть привязан к неконстантной ссылке. Если вы измените его, чтобы получить аргумент по ссылке на const, он работает.

Baz(const Foo<int>&);

Вы можете с радостью объявить конкретные операторы для определенных типов, если хотите:

template <typename S> struct Bar
{
template <typename T> operator Foo<T>();
operator Foo<bool>();
};

Bar<float> a{};
Foo<int> b = a; //calls operator Foo<T>
Foo<bool> c = a; //calls operator Foo<bool>
1

Другие решения


По вопросам рекламы [email protected]