- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我想让一个特征类应用于一个类型及其后代。这可能吗?
template <typename E>
struct Garble {
};
template <typename T>
struct wooble_traits;
template <typename E>
struct wooble_traits<Garble<E>> {
typedef E elem_type;
};
struct IntGarble : public Garble<int> {
};
typedef typename wooble_traits<IntGarble>::elem_type IGType;
//Error, wooble_traits<IntGarble> has no definition.
有没有办法代替说(借用和滥用 Java 符号):
template <typename E>
struct wooble_traits<? extends Garble<E>> {
typedef E elem_type
};
typedef typename wooble_traits<IntGarble>::elem_type IGType;
//Fine, IGType is an alias for int
注意:
尝试使 Dyp 的解决方案适应我的示例不起作用,因为 Garble 采用类型参数。似乎没有任何地方可以推断出该参数。
#include <boost/type_traits/is_base_of.hpp>
template <typename T, typename C = void>
struct wooble_traits;
template <typename T, typename E>
struct wooble_traits<T, typename boost::is_base_of<Garble<E>, T>::type> {
typedef E elem_type;
};
在 gcc-4.6 中产生:
g++ -I/usr/include/boost/utility -I/usr/include/boost/type_traits -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"main.d" -MT"main.d" -o "main.o" "../main.cpp"
../main.cpp:15:8: error: template parameters not used in partial specialization:
../main.cpp:15:8: error: ‘E’
make: *** [main.o] Error 1
这是可以理解的,因为 GCC 无法知道 E 的值。
最佳答案
对于基础类:
#include <type_traits>
template<bool b>
using stdbool_t = std::integral_constant<bool, b>;
template<class T, class U = std::true_type>
struct trait
: std::false_type
{};
struct foo {};
struct bar : foo {};
template<class T>
struct trait<T, stdbool_t<std::is_base_of<foo, T>{}>>
: std::true_type
{};
#include <iostream>
int main()
{
std::cout << std::boolalpha;
std::cout << trait<int>::value << "\n";
std::cout << trait<foo>::value << "\n";
std::cout << trait<bar>::value << "\n";
}
出于某种原因,当表达式依赖于(先前的)类型参数时,不允许专门处理非类型模板参数。
g++4.8.2 无法编译这个 btw (ICE),但它 works fine with clang++3.5
这是在两个编译器上编译的替代版本:
template<class T, class = void>
struct trait
: std::false_type
{};
struct foo {};
struct bar : foo {};
template<class T>
struct trait<T, typename std::enable_if<std::is_base_of<foo, T>{}>::type>
: std::true_type
{};
实际上,enable_if
不是必需的。 std::conditional
也可以工作,但 enable_if
在这里更短。
如果基础是模板特化,我们可以使用Jarod42's solution (我稍微修改了一下):
template<template<class...> class T, class U>
struct is_base_template_of
{
private:
template<class... V>
static auto test(const T<V...>&)
-> decltype(static_cast<const T<V...>&>(std::declval<U>()),
std::true_type{});
static std::false_type test(...);
public:
static constexpr bool value =
decltype(is_base_template_of::test(std::declval<U>()))::value;
};
template<class T>
struct trait<T,
typename std::enable_if<is_base_template_of<foo, T>::value>::type>
: std::true_type
{};
注意:这只适用于公共(public)继承(而且我认为它有一些进一步的限制:虚拟和某些多重继承的情况也不应该适用)。
这是“C++03 + boost”风格的相同类型特征的一个版本:
template<template<class> class T, class U>
struct is_base_template_of
{
private:
typedef char false_type;
typedef char(& true_type)[2];
template<class V>
static true_type test(const T<V>*);
static false_type test(...);
public:
static const bool value =
( sizeof(test(std::declval<typename std::remove_reference<U>::type*>()))
== sizeof(true_type));
};
关于c++ - 如何专门化 T 的特征类以及 T 的所有后代,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22622035/
我有一个带有模板函数的基类,该函数具有通用模板类型和专用版本。 #ifndef BASE_CLASS #define BASE_CLASS #include using namespace std;
我有这个 3D vector 模板 template class Vec3TYPE{ public: union{ struct{ TYPE x,y,z; }; struct{ TY
我是一名优秀的程序员,十分优秀!