虽然我很怀疑,但我很好奇是否可以从现有类型中提取原始类型模板参数,也许使用 RTTI。
例如:
typedef std::bitset<16> WordSet;
是否可以提取上述代码中的数字 16,而不用在其他地方进行硬编码?欢迎特定于编译器的实现,尽管我对
g++
特别感兴趣。
一般不可能选择任意模板参数。
但是,通常的做法是这样的:
template<int N>
struct foo {
static const int value = N;
};
以及类型
template<typename T>
struct foo {
typedef T type;
};
您可以通过
foo<39>::value
或 foo<int>::type
访问它。
如果您有特定类型,则可以使用部分模板特化:
template<typename>
struct steal_it;
template<std::size_t N>
struct steal_it< std::bitset<N> > {
static const std::size_t value = N;
};
同样的原理确实也适用于类型参数。现在您可以将任何位集传递给它,例如
steal_it< std::bitset<16> >::value
(注意使用 size_t,而不是 int!)。因为我们还没有可变的许多模板参数,所以我们必须将自己限制在特定的参数计数,并重复steal_it模板专门化以从1到N计数。另一个困难是扫描具有混合参数的类型(类型和非参数)类型参数)。解决这个问题可能并不简单。
如果你没有类型,而只有它的一个对象,你可以使用一个技巧,在编译时仍然获得一个值:
template<typename T>
char (& getN(T const &) )[steal_it<T>::value];
int main() {
std::bitset<16> b;
sizeof getN(b); // assuming you don't know the type, you can use the object
}
技巧是让函数模板自动推导类型,然后返回对字符数组的引用。该函数不需要定义,唯一需要的是它的类型。
您可以在 C++11 中使用参数推导和未求值上下文轻松完成此操作(请注意,为了方便起见,演示使用了 C++14 的变量模板功能)。
#include <type_traits>
#include <iostream>
template<int>
struct foo {};
template<int arg_N>
struct val {
static constexpr auto N = arg_N;
};
template<template <int> typename T, int N>
constexpr auto extract(const T<N>&) -> val<N>;
template<typename T>
constexpr auto extract_N = decltype(extract(std::declval<T>()))::N;
int main() {
std::cout << extract_N<foo<5>>;
}
我喜欢 Marc Garcia 的答案,因为它展示了如何以通用方式提取模板参数,但我相信他的示例可以更简单:
#include <type_traits>
#include <iostream>
template<int>
struct MyType {};
template<template <int> typename T, int N>
constexpr int extract(const T<N>&) { return N; }
int main() {
constexpr MyType<5> myObj;
std::cout << extract(myObj);
}
对于
std::bitset
,您可以只使用 size()
成员函数:
size_t sz = oh_my_word.size(); // sz is now 16
在一般情况下,您可以定义一个以类似方式返回大小的成员函数:
template <int N>
class Foo
{
public:
int size() const { return N; }
};
正如其他答案所述,对于
std::bitset
,您可以使用 size()
成员函数来获取大小,这应该是正确的选择,比任何其他技巧都要好。
针对一般情况有几个建议,几乎与我在下面建议的建议相似,但我仍然认为这个更简单:
template <template<std::size_t> typename T, std::size_t K>
auto extractSize(const T<K>&) {
return K;
}
int main() {
std::bitset<6> f1;
std::bitset<13> f2;
std::cout << extractSize(f1) << std::endl;
std::cout << extractSize(f2) << std::endl;
}
对于非常古老的 C++ 和整数类型,类枚举取代了非工作的 static const 声明。
template<int N> struct foo {
enum{value=N};
};