从实现中解耦类型特征定义

时间:2014-01-20 16:38:02

标签: c++ c++11 typetraits

让我们考虑下面的类,它检查提供的类型是否为字符串,并使用类型特征根据结果调用不同的函数。原始源具有对Obj的类型依赖性,这是一个简化的示例:

template <typename Obj> 
class example {
    public:            
        template <bool IdIsString = std::is_same<std::string, Obj>::value>
        typename std::enable_if<IdIsString, void>::type
        doStuff() {
            this->object->doSomething();
        }

        template <bool IdIsString = std::is_same<std::string, Obj>::value>
        typename std::enable_if<!IdIsString, void>::type
        doStuff()  {
            this->object->doSomethingElse();
        }
     private:
        AnyObject object;
};

如何在不提供定义中的每个类型特征的情况下,将定义(例如将其存储在example_inline.hpp中)与类解耦?

理想的解决方案如下:

// header.hpp
template <typename Obj> 
class example {
    public:
        void doStuff(); 
}

// header_inline.hpp
template <typename Obj>
template <bool IdIsString = std::is_same<std::string, Obj>::value>
typename std::enable_if<IdIsString, void>::type
example::doStuff() {
   // ...
}

// ...

以上显然是不可能的。一种解决方案是将type_trait函数与类分离并将其放入详细命名空间,但这意味着我必须始终将AnyObject(在这种意义上,由函数修改的所有对象)传递给它不是很优雅。

这个问题有一个很好的解决方案吗?我非常希望有问题的标题可以轻松阅读,而不会因为大量的enable_if而混乱。

感谢您对此事的任何意见。

2 个答案:

答案 0 :(得分:3)

您可以根据std::is_same

的返回值进行重载
template<typename T>
class example
{
private:
    void doStuff(std::true_type)
    {
        obj->doSomething();
    }

    void doStuff(std::false_type)
    {
        obj->doSomethingElse();
    }
public:
    void doStuff()
    {
        doStuff(std::is_same<T, std::string>{});
    }
};

答案 1 :(得分:2)

在这个简单的例子中,您还可以在类模板的模板参数上专门化doStuff

#include <iostream>
#include <string>

template<class T>
struct example
{ void doStuff(); };

template<class T>
void example<T>::doStuff()
{ std::cout<<"default\n"; }

template<>
void example<std::string>::doStuff()
{ std::cout<<"string\n"; }

int main()
{
    example<int>{}.doStuff();
    example<std::string>{}.doStuff();
}

Live example