我目前正在编写一个模板,根据输入的类别进行不同的操作。
我希望将3个案例添加到我的特质课程中。
一个。该类型有一个typedef
type_category
,使用它。B中。该类型没有typedef,使用类型
regular_tag
(最常见的情况)℃。我的专精
std::list<T>
使用special_tag
类型T
。
我该如何管理?做A.和C.或B.和C.很简单。但我不知道如何获得所有3。
一个例子可能会让人们更容易理解。
class Foo
{
typedef foo_tag type_category;
}
class Bar;
my_traits<Foo>::type(); // makes a foo_tag
my_traits<Bar>::type(); // makes a regular_tag
my_traits<std::list<Baz>>::type(); // makes a special_tag because I want special list proce
ssing。
答案 0 :(得分:7)
脚手架可能如下所示:
template <typename T>
struct MyTrait
{
typedef typename MyHelper<T, CheckForType<T>::value>::type tag;
};
template <typename T>
struct MyTrait<std::list<T>>
{
typedef special_tag tag;
};
我们需要帮手:
template <typename T, bool>
struct MyHelper
{
typedef regular_tag tag;
};
template <typename T>
struct MyHelper<T, true>
{
typedef typename T::type_category tag;
};
现在我们只需要一个类型特征来检查成员typedef:
template<typename T>
struct CheckForType
{
private:
typedef char yes;
typedef struct { char array[2]; } no;
template<typename C> static yes test(typename C::type_category*);
template<typename C> static no test(...);
public:
static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};
用法:
MyTrait<Foo>::tag
答案 1 :(得分:0)
template<class T>
T::type_category getType(T t, typename T::type_category c=typename T::type_category())
{ return c;}
template<class T>
regular_tag getType(T t, ...)
{ return regular_tag();}
template<class T>
special_tag getType(std::list<T> t, typename std::list<T>::type_category c=typename std::list<T>::type_category())
{ return special_tag();}
int main() {
auto a = getType(int);
auto b = getType(std::iterator_traits<char*>);
auto c = getType(std::list<char>);
}
我对SFINAE并不是那么好,所以我怀疑这甚至可以编译,但是这样的事情是看的方向。
答案 2 :(得分:0)
Kerrek的代码有效,但以下代码更短,更通用:
template <typename T,typename DefaultType>
class MyTrait
{
template <typename C> static DefaultType test( ... );
template <typename C> static typename C::type_category test( typename C::type_category * );
public:
using type = decltype( test<T>(nullptr) );
};
我之所以说Kerrek的代码不是通用的,是因为它要求你对类型进行硬编码&#34; special_tag&#34;所以你的类MyTrait将始终使用相同的默认标记。我提供的代码允许您使用具有不同默认值的MyTrait类。例如,如果未定义 type_category ,则可能会在代码中的某个位置发生默认为 int ,但在其他地方,您希望它是的浮即可。
让我们看一个例子。假设我们设计了一个类,它用于将容器类(例如标准库 vector )作为模板参数。在我们的课程中,我们希望使用相同的 size_type 作为基础容器。但是,有人可能会向我们提供一个未定义 size_type 的容器(例如, valarray 未定义 size_type )。在这种情况下,让我们假装我想使用 int 作为默认值(您应该像其他标准容器一样使用 size_t ,但如果我更改了代码你不能告诉代码实际上是有效的。对于这种情况,我改变了#34; MyTrait&#34;的类名。到&#34; size_typeof&#34;,我改变了&#34; type_category&#34;到&#34; size_type&#34; (因为这是我想要寻找的东西)。下面给出了此场景的一些代码以及用于查看确定变量类型的示例main函数:
#include <iostream>
#include <vector>
#include <valarray>
#include <typeinfo>
template <typename T,typename DefaultType>
class size_typeof
{
template <typename C> static DefaultType test( ... );
template <typename C> static typename C::size_type test( typename C::size_type * );
public:
using type = decltype( test<T>(nullptr) );
};
template <typename ContainerType>
class Matrix {
private:
// Change int to size_t in real code.
using size_type = typename size_typeof<ContainerType,int>::type;
size_type Rows;
size_type Cols;
public:
Matrix( size_t rows, size_t cols ) : Rows(rows), Cols(cols) {}
size_type rows(){ return Rows; }
size_type cols(){ return Cols; }
};
int main()
{
// Give the matrices some nonzero dimensions
Matrix<std::vector<double>> vec(5,2);
Matrix<std::valarray<double>> val(4,3);
// vectors have a size_type, almost always defined as size_t.
// So this should return your compiler's code for size_t
// (on my computer, this is "m")
std::cout << typeid( vec.rows() ).name() << std::endl;
// valarrays do not have a size_type.
// So this should return your compiler's code for int
// (on my computer, this is "i")
// It should return this code, since we used int as the default
// size_type in the Matrix class
std::cout << typeid( val.rows() ).name() << std::endl;
return 0;
}
确定。太棒了。但是假设我确实只想使用DefaultType的硬编码默认值,而不必将DefaultType指定为模板参数。你猜怎么着?模板参数默认值。只需定义size_typeof,如:
template <typename T,typename DefaultType = int>
class size_typeof {
...
};
你很高兴。无需指定默认类型&#34; int&#34;了。例如,在我们的Matrix类中,我们可以使用
using size_type = size_typeof<ContainerType>;
结束。