模板专业化'即时'

时间:2017-05-07 08:41:31

标签: c++ templates template-specialization

假设我有一个空的模板化结构foo

template <typename T> struct foo {};

一个专门研究它的宏

#define SPECIALIZE(class_name) \
template <> \
struct foo<class_name> { \
    static const std::string value; \
}; \
const std::string foo<class_name>::value = #class_name;

我想有一个方法可以打印它所拥有的类的名称作为模板参数。通常,我会这样做:

template <typename T>
void print() {
    std::cout << foo<T>::value << std::endl;
}

SPECIALIZE(std::vector<int>)
int main() {
    print<std::vector<int>>();
    return 0;
}

但是,我发现必须明确记录该类非常烦人并且容易出错,因为您必须确保一次性调用该宏。

我想做那样的事情:

template <typename T>
void print() {
    if (notdefined(foo<T>::value)) {
        SPECIALIZE(T)
    }
    std::cout << foo<T>::value << std::endl;
}

这当然不可能这样。

你对我如何实现这个目标有所了解吗?

2 个答案:

答案 0 :(得分:1)

我想我会通过定义networking_traits模板专业化的概念来实现这一点,该专业化包含您需要的任何信息(重新序列化,创建,解析,命名等)

简单的例子:

#include <iostream>

//
// define the concept of a getting a type's universal name
// in terms of a networking_traits<> template class specialisation

template<class T> struct networking_traits;

template<class T>
constexpr decltype(auto) get_universal_name()
{
    auto traits = networking_traits<T>();
    return traits.universal_name();
}


// some object...
struct ObjectA
{
};

// define a traits object for it
template<> struct networking_traits<ObjectA>
{
    constexpr auto universal_name() const { return "ObjectA"; }
};


// some other object
struct ObjectB
{
};

// define another traits object - note the different (but compatible) type
// of the universal_name return type
template<> struct networking_traits<ObjectB>
{
    static const std::string& universal_name() { 
        static const auto s = std::string("ObjectB");
        return s;
    }
};


int main()
{
    std::cout << get_universal_name<ObjectA>() << std::endl;
    std::cout << get_universal_name<ObjectB>() << std::endl;
}

答案 1 :(得分:1)

您尝试做的是将模板参数作为字符串。 不幸的是,这个有两个问题

  1. 这是明确被禁止的&#34;只是因为&#34;
  2. 显然,在C ++ 11中使用重模板技巧有一种解决方法
  3. 严重的问题实际上是2,因为这意味着C ++在这个领域可能永远不会得到任何合理的东西(由于C ++中的一些奇怪的原因,如果使用模板元编程存在一个非常复杂的半工作和逻辑上破解的解决方案那么没有合理的解决方案将被寻找)。

    我的建议只是添加一个显式成员函数,返回const char *

    struct Protocol {
        virtual const char *name() const = 0;
    };
    
    struct TCP : Protocol {
        const char *name() const { return "TCP"; }
        ...
    };