moi*_*rex 6 c++ templates metaprogramming c++20
以下代码适用于 GCC(至少适用于 GCC 10.1.0),但不适用于 MSVC 和 Clang。我不确定它在 C++ 标准中是否合法。
我正在尝试计算template template类型中的参数。
以下代码是否为有效的 C++ 代码,如果是,那么如何使它们在 Clang 和 MSVC 中工作,如果不是,是否有替代方法?
template <template<typename...> typename T>
struct template_count {
static constexpr unsigned value = 0;
};
template <template<typename> typename T>
struct template_count<T> {
static constexpr unsigned value = 1;
};
template <template<typename, typename> typename T>
struct template_count<T> {
static constexpr unsigned value = 2;
};
template <template<typename, typename, typename> typename T>
struct template_count<T> {
static constexpr unsigned value = 3;
};
template <typename one, typename two, typename three>
struct test {
};
int main() {
return template_count<test>::value;
}
Run Code Online (Sandbox Code Playgroud)
经过twitter上某人的提示后,我找到了一个适用于 GCC 和 Clang 的更好的解决方案(链接到编译器资源管理器)(在 github 中):
#include <type_traits>
#include <cstddef>
struct variadic_tag {};
struct fixed_tag : variadic_tag {};
struct number_signature {};
template<std::size_t V>
struct ParameterNumber : number_signature {
constexpr static auto value = V;
};
template<typename T>
concept NumberObjConcept = std::is_base_of_v<number_signature, T>;
template<template<typename> typename>
auto DeduceArgs() -> ParameterNumber<1>;
template<template<typename, typename> typename>
auto DeduceArgs() -> ParameterNumber<2>;
template<template<typename, typename, typename> typename>
auto DeduceArgs() -> ParameterNumber<3>;
template<template<typename, typename, typename, typename> typename>
auto DeduceArgs() -> ParameterNumber<4>;
template<template<typename, typename, typename, typename, typename> typename>
auto DeduceArgs() -> ParameterNumber<5>;
template<template<typename, typename, typename, typename, typename, typename> typename>
auto DeduceArgs() -> ParameterNumber<6>;
template<template<typename, typename, typename, typename, typename, typename, typename> typename>
auto DeduceArgs() -> ParameterNumber<7>;
template<template<typename, typename, typename, typename, typename, typename, typename, typename> typename>
auto DeduceArgs() -> ParameterNumber<8>;
template<template<typename, typename, typename, typename, typename, typename, typename, typename, typename> typename>
auto DeduceArgs() -> ParameterNumber<9>;
template<template<typename, typename, typename, typename, typename, typename, typename, typename, typename, typename> typename>
auto DeduceArgs() -> ParameterNumber<10>;
template<template<typename...> typename F>
auto DeduceTemplateArgs(variadic_tag) -> ParameterNumber<1000000000>; // a meaningless big number
template<template<typename...> typename F>
auto DeduceTemplateArgs(fixed_tag) -> decltype(DeduceArgs<F>());
template <typename one, typename two, typename three>
struct test {
};
#define __DEDUCE_TEMPLATE_ARGS(c) decltype(DeduceTemplateArgs<c>(fixed_tag{}))
int main() {
return __DEDUCE_TEMPLATE_ARGS(test)::value;
}
Run Code Online (Sandbox Code Playgroud)
当然,上面的代码在这种情况下会失败:
template <template<typename> typename>
struct test {};
Run Code Online (Sandbox Code Playgroud)
这对于大多数情况来说都很好。