我有一个包含元组的模板类。
template <class... SomeTypes>
class Foo
{ ... };
如何对 SomeTypes 参数包中包含的类型应用约束?例如,如果我想确保所有类型都符合这个std::movable
概念?
如果SomeTypes
也是模板怎么办?
template < template<typename> class... SomeTypes>
class Bar
{ ... };
以下是我正在寻找的更具体的情况。该代码不应该(并且不会)编译,因为FooB
它不可复制。
不幸的是,编译器在遇到这种情况时并没有给出最清晰的错误信息(在我处理的实际代码中,类型更加复杂,最终导致了大量错误信息)。我希望可以添加一些子句,requires
让它FooContainer
给出更清晰的错误信息。
#include <tuple>
#include <concepts>
template <typename ContainerType>
class Foo
{
};
template <typename ContainerType>
class FooA : public Foo<ContainerType>
{
public:
int some_data {0};
void DoSomething()
{
some_data++;
}
};
template <typename ContainerType>
class FooB : public Foo<ContainerType>
{
public:
// non-copyable object
FooB() = default;
FooB( const FooB& ) = delete;
FooB& operator=( const FooB& ) = delete;
~FooB() = default;
int some_data {0};
void DoSomething()
{
some_data++;
}
};
template < template<typename> class... SomeTypes>
// requires (std::copyable<SomeTypes...>) ???
class FooContainer
{
public:
std::tuple<SomeTypes<FooContainer>...> my_tuple;
template <std::size_t I = 0, std::enable_if_t<I == sizeof...(SomeTypes)>* = nullptr>
void DoAllThings()
{
}
template <std::size_t I = 0, std::enable_if_t<I < sizeof...(SomeTypes)>* = nullptr>
void DoAllThings()
{
std::get<I>(my_tuple).DoSomething();
DoAllThings<I + 1>();
}
};
using MyContainer = FooContainer<FooA, FooB>;
int main()
{
MyContainer my_bar;
my_bar.DoAllThings();
MyContainer my_bar2 = my_bar;
}
--编辑 2--
因此,在尝试了这里的一些建议之后,我想到最接近我想要的就是使用外部静态函数来进行检查。
template <typename FooType>
requires (std::copyable<FooType>)
constexpr bool FooTypeCheck()
{
return true;
}
static_assert(FooTypeCheck<FooA<int>>());
这给了我想要的检查(派生的 Foo 类是否可复制),因此如果检查失败,编译器的输出更容易阅读。对于类型检查来说,ContainerType 无关紧要,所以我只传递了一个 int 值。不幸的是,这也意味着我需要为每个派生的 Foo 类添加 static_assert,而我传递给 ContainerType 的 int 值有点奇怪。
--最终编辑(答案)-- 我感谢@Ted Lyngmo的回答,因为它接近我的需求。由于ContainerType参数只是CRTP的一部分,因此对于约束而言,它实际上无关紧要,而且我可以直接使用int,这样解决方案就更简单一些了。
template <template <typename> class FooType>
concept FooTypeCheck = std::copyable<FooType<int>>;
template < template<typename> class... SomeTypes>
requires (... && FooTypeCheck<SomeTypes>)
class FooContainer
{ ... };