使用enable_if与功能模板交朋友

时间:2015-10-07 08:53:33

标签: c++ c++11 c++14

Edit2:上一个解决方案导致了一些错误,所以现在我被我的成员公开了。

编辑: 我以为我有一个解决方案,直到我尝试了Clang。

错误是无法找到相应的模板。

然而,如果我在path函数的第一个前向声明之前添加它,它就会自行解决:

template<typename T, typename U=void>
Path<T> path(const T& obj);

但是GCC不再构建它了所以我用一些宏来修复它......

#if defined(__clang__)
  template<typename T, typename U = void>
  Path<T> path(const T& obj);
#elif defined(__GNUC__)
  template<typename T, typename U>
  Path<T> path(const T& obj);
#endif

以下是测试代码的方法:http://goo.gl/dafN8K

原始问题

我找到了以下答案,但他们没有解决我的问题:

Overloading friend operator << for template class

- &GT;对我不好,因为我想成为模板,而不是使用类模板参数的专业,并且不想在这个类中内联我的代码。

Issue with friend template functions clang++ / msvc++ and enable_if

- &GT;我不想更改我的函数以在返回类型中使用enable_if,这会使代码完全无法读取。

所以,这是我最小的非工作代码。如果将m_path_cache公开,但当然我不想在我的公共界面中使用缓存,它就有用...

#include <type_traits>
class IdentifiedObjectAbstract
{
};

template<typename T>
struct Path;

namespace ANamespace
{
template<typename T, std::enable_if_t<
             std::is_base_of<
                 IdentifiedObjectAbstract,
                 T
                >::value
             >* = nullptr
         >
Path<T> path(const T& obj);

template<typename T, std::enable_if_t<
             !std::is_base_of<
                 IdentifiedObjectAbstract,
                 T
                >::value
             >* = nullptr
         >
Path<T> path(const T& obj);
}


template<typename T>
class IdentifiedObject : public IdentifiedObjectAbstract
{   
    ////////
    // I need to befriend the first template function here.
    ////////

    private:
        mutable Path<T> m_path_cache;   
};

template<typename Object>
struct Path
{
};

namespace ANamespace
{
template<typename T, std::enable_if_t<
             std::is_base_of<
                 IdentifiedObjectAbstract,
                 T
                >::value
             >* = nullptr
         >
Path<T> path(const T& obj)
{
    return obj.m_path_cache;
}

template<typename T, std::enable_if_t<
             !std::is_base_of<
                 IdentifiedObjectAbstract,
                 T
                >::value
             >* = nullptr
         >
Path<T> path(const T& obj)
{
    return Path<T>{};
}
}

class A : public IdentifiedObject<A>
{};

void f()
{
     A a;
    auto path = ANamespace::path(a);

}

我也尝试过如下功能:

template<typename U>
friend Path<U> path(const U& obj);

template<typename U, typename V>
friend Path<U> path(const U& obj);

template <typename U, std::enable_if_t<std::is_base_of<IdentifiedObjectAbstract, U>::value>*>
friend  Path<U> path(const U& obj);

template <typename U, std::enable_if_t<std::is_base_of<IdentifiedObjectAbstract, U>::value>* = nullptr>
friend  Path<U> path(const U& obj);

但无济于事。

0 个答案:

没有答案