基于 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);
// ...
};
在评论之后,为了禁止从 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;
如果我们想替换复制构造函数并避免从 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;
我有一个带有单个 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);
// ...
};
在评论之后,为了禁止从 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;
如果我们想替换复制构造函数并避免从 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;