我有一个模板:
template<typename... Ts> //T1,T2,T3,...
struct foo {
//my struct
};
我想分别对T1,T3,T5,......(“奇数类型”)以及T2,T4,T6,......(“偶数类型”)进行static_assert
检查。
我找到了这个简单的解决方案:
template<size_t N, typename... Ts>
struct perform_checks {};
template<size_t N, typename T, typename U, typename... Ts>
struct perform_checks<N, T, U, Ts...> : perform_checks<N, Ts...>
{
//check for odd types
static_assert(std::is_default_constructible<T>::value,"failure");
//check for even types
static_assert(std::is_copy_constructible<U>::value,"failure");
};
N
参数允许它结束。我这样用它:
template<typename... Ts>
struct foo {
perform_checks<0,Ts...> hello;
};
这似乎工作正常。但是有可能避免hello
变量吗?我从不将它用于任何其他目的。
答案 0 :(得分:2)
私下从foo
发送perform_checks<>
:
template <typename... Ts> struct foo : private perform_checks<Ts...> {
// stuff
};
哦,摆脱你不需要的N
参数:
template <typename... Ts> struct perform_checks {};
template <typename T> struct perform_checks<T> {
template <typename U> struct dependent_name_hack : std::false_type {};
static_assert(dependent_name_hack<T>::value,
"Odd number of parameters not acceptable.");
};
template <typename T, typename U, typename... Ts>
struct perform_checks<T, U, Ts...> : perform_checks<Ts...> {
//check for odd types
static_assert(std::is_default_constructible<T>::value,"failure");
//check for even types
static_assert(std::is_copy_constructible<U>::value,"failure");
};
答案 1 :(得分:2)
您可以通过以下方式使用enable_if
1(和boost :: mpl)或多或少:
#include <boost/mpl/and.hpp>
template<size_t N, typename... Ts>
struct perform_checks {};
template<size_t N, typename T, typename U, typename... Ts>
struct perform_checks<N, T, U, Ts...> : perform_checks<N, Ts...>
{
typedef boost::mpl::and_<std::is_default_constructible<T>::type,
std::is_copy_constructible<U>::type> type;
};
template < class... Ts,
class = typename std::enable_if<perform_checks<0, Ts...>::type>
struct foo {
//my struct
};
答案 2 :(得分:2)
OP中foo
的唯一目的是在实例化时触发检查。这就是你需要变量hello
的原因:它是foo
的实例化。
我宁愿在<type_traits>
中遵循特征的方法。更确切地说,我会将perform_checks
变为class
(或struct
),其成员static constexpt bool
value
成员true
或{false
1}}取决于给定类型是否通过测试。然后,如果static_assert
为假,我会使用单个value
来停止编译。
我的解决方案假设模板类型参数的数量是偶数,如下:
#include <type_traits>
template<typename First, typename Second, typename... Others>
struct perform_checks :
std::integral_constant<bool,
perform_checks<First, Second>::value && // Checks First and Second
perform_checks<Others...>::value // Recursively "calls" itself on Others
> {
};
// This specialization finishes the recursion and effectively performs the test
template<typename First, typename Second>
struct perform_checks<First, Second> :
std::integral_constant<bool,
std::is_default_constructible<First>::value && // Checks First
std::is_copy_constructible<Second>::value // Checks Second
> {
};
这是一个简单的测试:
struct NonDefaultConstructible {
NonDefaultConstructible() = delete;
};
struct NonCopyConstructible {
NonCopyConstructible(const NonCopyConstructible&) = delete;
};
int main() {
static_assert(perform_checks<int, double>::value, "Failure");
static_assert(perform_checks<int, int, double, double>::value, "Failure");
static_assert(!perform_checks<NonDefaultConstructible, int>::value, "Failure");
static_assert(!perform_checks<int, NonCopyConstructible>::value, "Failure");
static_assert(!perform_checks<int, int, double, NonCopyConstructible>::value, "Failure");
}
请注意,未创建任何变量。