Перегрузка на основе параметра шаблона bool - PullRequest
1 голос
/ 12 января 2020

У меня есть шаблон класса с одним параметром шаблона bool. Я хочу иметь возможность неявного преобразования из экземпляров с параметром, равным true, в те, где он равен false.

Я пытался сделать это (для конструктора копирования), но проблема в том, что когда у меня Foo<true>, теперь есть две версии одного и того же конструктора (с одинаковой подписью).

template <bool B>
class Foo
{
public:
    Foo(const Foo& other);
    Foo(const Foo<true>& other);
};

Не знаете, как это реализовать? Я также намереваюсь иметь подобный код для конструктора перемещения и присваивания.

Ответы [ 3 ]

2 голосов
/ 12 января 2020

Вы можете применить SFINAE , чтобы сделать Foo(const Foo<true>& other) действительным только с Foo<false>.

template <bool B>
class Foo
{
public:
    Foo(const Foo& other);
    template <bool b = B, std::enable_if_t<!b>* = nullptr> // when b is false
    Foo(const Foo<true>& other);
};
1 голос
/ 12 января 2020

Начиная с C ++ 20, вы сможете написать что-то вроде этого:

template<bool B>
class Foo
{
public:
    Foo(const Foo& other) 
        : Foo(other, Tag{}) { }

    Foo(const Foo<true>& other) 
    requires(!B)               
        : Foo(other, Tag{}) { }

private:
    struct Tag {};

    template<bool B1>
    Foo(const Foo<B1>& other, Tag) {
        // ...
    }
};

Здесь вместо SFINAE используется requires -clause (см. Songyuanyao's ответ). Закрытый конструктор с параметром Tag может использоваться для избежания дублирования кода. Возможно, вам также понадобится сделать Foo<true> другом Foo<false>.

0 голосов
/ 12 января 2020

Нет необходимости использовать enable_if, если вам нужно различить guish между Foo<false> и Foo<true>. Должно работать следующее:

template <bool B>
class Foo
{
public:
    Foo(const Foo<true>& other);
    Foo(const Foo<false>& other);
    // ...
};

https://godbolt.org/z/_9NNhR


После комментария, чтобы запретить преобразование из false в true, следующий код будет работать :

template <bool B>
class Foo
{
public:
    template<bool Other>
    Foo(const Foo<Other>& other) {}
    Foo() {}
};

template <>
template <>
Foo<true>::Foo(const Foo<false>&) = delete;

https://godbolt.org/z/NjghXK


Если мы хотим заменить копию ctor и избежать преобразования из false в true:

template <bool B>
class Foo
{
public:
    Foo(const Foo<true>& other) {
        std::cout << true << " set to " << B << std::endl;
    }
    Foo(const Foo<false>& other) {
        std::cout << false << " set to " << B << std::endl;
    }
    Foo() {}
};

template <>
Foo<true>::Foo(const Foo<false>&) = delete;

https://godbolt.org/z/zt8VMb

...