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);
但无济于事。