我有一个应该有一个朋友的模板类:一个make_object
函数,可以扣除某些类型和值。我希望只与模板类类型匹配的那些实例化成为朋友。我的代码的简化版本如下:
template<size_t S, typename T>
class Object {
private:
Object(T t);
template<typename U, typename... Args>
friend auto make_object(U, Args... args);
};
template<typename U, typename... Args>
inline auto make_object(U u, Args... args)
{
constexpr size_t S = sizeof...(Args);
return std::unique_ptr<Object<S, U>>(new Object<S, U>(u));
}
[以此代码为例,我希望只将make_object
与对象的typename U
匹配的typename T
的那些实例作为朋友。那有可能吗?
如果您的要求只是简单地将功能模板与与T
相同的模板参数作为朋友,那么就足够了:
#include <cstdint>
template <typename T, typename ... TArgs>
auto make_object(T, TArgs...);
template<std::size_t size, typename T>
class Object {
private:
Object(T t);
friend auto make_object<T>(T);
};
template <typename T, typename ... TArgs>
auto make_object(T t, TArgs... args) {
Object<0u, T>{t}; // Compiles
}
template <>
auto make_object<float>(float f) {
// Error: Constructor is private
Object<0u, int>{static_cast<int>(f)};
}
您可以使用一个类来将U
的make_object
参数(必须与T
的Object
匹配)与Args
参数包分开,该参数包不必匹配。然后,与helper类成为朋友,为函数的所有实例化提供对private
的Object
成员的访问。
template<typename U> struct make_object_t; template<std::size_t S, typename T> class Object { private: Object(T t); friend class make_object_t<T>; }; template<typename U> struct make_object_t { template<typename... Args> static auto make_object(U u, Args... args) { constexpr std::size_t S = sizeof...(Args); return std::unique_ptr<Object<S, U>>(new Object<S, U>(u)); } };
最后,编写一个帮助器函数以从API隐藏该类:
template<typename U, typename... Args> auto make_object(U&& u, Args&&... args) { return make_object_t<U>::template make_object<Args...>(std::forward<U>(u), std::forward<Args>(args)...); }
现在,例如这有效
int main() { std::unique_ptr<Object<3, int>> ptr = make_object(5, 'a', 0x0B, "c"); }
但是,例如
make_object_t<char>
无法使用Object<S, int>::Object
:
template<>
struct make_object_t<char> {
template<typename... Args>
static auto make_object(char u, Args... args) {
constexpr std::size_t S = sizeof...(Args);
return std::unique_ptr<Object<S, int>>(new Object<S, int>(u));
}
};
int main() {
// error here from instantiation of above function template
auto oops = make_object('n', 'o');
}
如果您想拥有一个朋友模板,则可以像您的示例一样,将模板的所有实例设为一个朋友,或者可以将一个完全专业化的朋友设为一个朋友。
据我所知,make_object()
是一种便利功能模板,利用模板自变量推导来创建Object
对象。