与参数匹配的朋友模板函数实例

问题描述 投票:1回答:4

我有一个应该有一个朋友的模板类:一个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的那些实例作为朋友。那有可能吗?

c++ templates instantiation friend
4个回答
1
投票

如果您的要求只是简单地将功能模板与与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)};  
}

Compiler Explorer


1
投票

您可以使用一个类来将Umake_object参数(必须与TObject匹配)与Args参数包分开,该参数包不必匹配。然后,与helper类成为朋友,为函数的所有实例化提供对privateObject成员的访问。

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');
}

1
投票

如果您想拥有一个朋友模板,则可以像您的示例一样,将模板的所有实例设为一个朋友,或者可以将一个完全专业化的朋友设为一个朋友。


0
投票

据我所知,make_object()是一种便利功能模板,利用模板自变量推导来创建Object对象。

© www.soinside.com 2019 - 2024. All rights reserved.