Sus*_*rak 3 c++ variadic-templates
我希望能够在编译时使用 检查类的static_assert所有可变参数是否以相同的大小创建。
这是我想出的代码,但它不起作用:
template<typename... Args>
class MyClass {
static size_t arg_reference_size;
constexpr static bool size_is_equal() {
return true;
}
template<typename First, typename... Others>
constexpr static bool size_is_equal() {
return arg_reference_size == sizeof(First) && size_is_equal<Others...>();
}
template<class First, typename... Others>
constexpr static bool check_args_size() {
arg_reference_size = sizeof(First);
return size_is_equal<Others...>();
}
static_assert(size_is_equal<Args...>(), "");
}
Run Code Online (Sandbox Code Playgroud)
我会将类型特征移出类:
template<class T, class... R>
inline constexpr bool is_same_size_v = (... && (sizeof(T) == sizeof(R)));
template<typename... Args>
class MyClass {
static_assert(is_same_size_v<Args...>);
};
int main() {
MyClass<int, unsigned> x;
//MyClass<char, long double> y; // will very likely fail
}
Run Code Online (Sandbox Code Playgroud)
如果您想将类型特征保留在类内部并基于您当前的想法,您可以确保声明size_is_equal()返回一个类型,该类型的变量设置static constexpr为true或false取决于模板参数。您不需要该函数的实际实现。返回的类型就足够了。这里std::integral_constant<bool, true>orstd::integral_constant<bool, false>将被返回 - 并且它们是带有static constexpr bool value变量的不同类型。然后您可以使用它decltype(<the returned type>)::value来获得实际结果。
template<typename... Args>
class MyClass {
template<typename First, typename... Others>
static auto size_is_equal() ->
std::integral_constant<bool, (... && (sizeof(First) == sizeof(Others)))>;
static constexpr bool size_is_equal_v =
decltype(size_is_equal<Args...>())::value;
static_assert(size_is_equal_v, "nope");
};
Run Code Online (Sandbox Code Playgroud)
第三种选择,如果您确实希望函数具有实现并且无法使用 C++17 折叠表达式并且需要递归:
#include <type_traits>
template <typename... Args>
class MyClass {
template <typename... Ts>
// SFINAE to only make this match if the param pack is empty:
constexpr static typename std::enable_if<sizeof...(Ts) == 0, bool>::type
size_is_equal() {
return true; // or `false` if an empty parameter pack should not be
// allowed
}
template <typename> // a single parameter to terminate recursion
constexpr static bool size_is_equal() {
return true; // a single parameter is always true
}
// Take at least two template parameters and pass one of them on to the
// recursive call:
template <typename First, typename Second, typename... Others>
constexpr static bool size_is_equal() {
return sizeof(First) == sizeof(Second) &&
size_is_equal<Second, Others...>();
}
static_assert(size_is_equal<Args...>(), "not equal size");
};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
157 次 |
| 最近记录: |