基于 bool 模板参数的重载

Overloading based on bool template parameter

我有一个带有单个 bool 模板参数的模板 class。我希望能够从参数等于 true 的实例化隐式转换为参数等于 false.

的实例化

我试过这样做(对于复制构造函数),但问题是当我有 Foo<true> 时,同一个构造函数现在有两个版本(具有相同的签名)。

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

不确定如何实施?我也打算为移动构造函数和赋值编写类似的代码。

从 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) {
        // ...
    }
};

这里用requires-clause代替SFINAE(见songyuanyao的回答)。带有 Tag 参数的私有构造函数可用于避免代码重复。您可能还需要让 Foo<true> 成为 Foo<false> 的朋友。

您可以应用 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);
};

如果需要区分Foo<false>Foo<true>,则不需要使用enable_if。以下应该有效:

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


如果我们想替换复制构造函数并避免从 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