使用可变参数模板标记转换元函数

时间:2016-08-24 08:35:08

标签: c++11 variadic-templates

我需要转换这个"有限的"使用可变参数模板将元函数转换为C ++ 11样式:

  

目标 是实现一个转换给定TAG的元函数   尽管给出了所有的基本标签,但递归到BASE_TAG。如果不   基类匹配,不执行强制转换(强制转换的结果是   原始TAG类型。)

我需要按照此处发布的类型进行Tag调度: http://barendgehrels.blogspot.de/2010/10/tag-dispatching-and-inheritance.htmlhttp://barendgehrels.blogspot.de/2010/10/tag-dispatching-by-type-tag-dispatching.html

原始版本(工作但基类数量有限(BTx)):

template<typename TAG, typename BASE_TAG, typename BT2 = void, typename BT3 = void, typename BT4 = void, typename BT5 = void, typename BT6 = void, typename BT7 = void>
struct tag_cast
{
    using type = typename std::conditional<std::is_base_of<BASE_TAG, TAG>::value, BASE_TAG, typename tag_cast<TAG, BT2, BT3, BT4, BT5, BT6, BT7, void>::type>::type;
};
template<typename TAG>
struct tag_cast<TAG, void, void, void, void, void, void, void>
{
    using type = TAG;
};

我想做到这一点:

template<typename TAG, typename BASE_TAG, typename ... OTHER_BASE_TAGS>
struct tag_cast
{
    /* If TAG is derived from BASE_TAG, set type to BASE_TAG. Search in other base tags if specified (or set the type to itself if not found anywhere) */
    using type = typename std::conditional<std::is_base_of<BASE_TAG, TAG>::value, BASE_TAG, typename tag_cast<TAG, OTHER_BASE_TAGS ..., void>::type>::type;
};

template<typename TAG>
struct tag_cast<TAG, void>
{
    using type = TAG;
};

当我尝试使用它时:

class BaseTag1 {};
class BaseTag2 {};
class BaseTag3 {};
class BaseTag4 {};

class Tag1 : BaseTag1 {};

/* Dispatch the tag */
using ToothProfileTag = typename tag_cast<Tag1, BaseTag1, BaseTag2, BaseTag3, BaseTag4>::type;

它抱怨没有定义类型属性:

  

错误:'struct tag_cast'中没有名为'type'的类型

非常感谢任何愿意帮助的人......

1 个答案:

答案 0 :(得分:2)

您当前的代码不起作用,因为部分特化是针对<TAG,void>的,但最终会有一些void s等于基类的数量。

我会将主模板作为基本案例,并使递归案例成为部分特化

template<typename TAG, typename... OTHER_BASE_TAGS>
struct tag_cast
{
    using type = TAG;
};

template<typename TAG, typename BASE_TAG, typename ... OTHER_BASE_TAGS>
struct tag_cast<TAG, BASE_TAG, OTHER_BASE_TAGS...>
{
    using type = typename std::conditional<
                     std::is_base_of<BASE_TAG, TAG>::value, 
                     BASE_TAG, 
                     typename tag_cast<TAG, OTHER_BASE_TAGS ...>::type
                 >::type;
};

Live Demo