声明模板类的模板友元函数

问题描述 投票:0回答:2

我有一个类模板

Obj
和一个函数模板
make_obj
Obj
定义了一个
private
单个构造函数,它引用了要绑定到的模板类型。

template <typename T>
class Obj {
  private:
    T& t;
    Obj(T& t)
        : t{t}
    { }
};

template <typename T>
Obj<T> make_obj(T& t) { 
    return {t};
}

我想要的是将

make_obj
函数声明为
friend
以便它可以创建
Obj
的,但没有其他人可以(除了通过复制 ctor)。


我试过几个朋友声明,包括

friend Obj make_obj(T&);

template <typename T1, typename T2>
friend Obj<T1> make_obj(T2&);

后者是对

make_obj
类的
Obj
朋友进行所有模板实例化的不太理想的尝试。但是,在这两种情况下,我都会遇到相同的错误:

error: calling a private constructor of class 'Obj<char const[6]>'
    return {t};
           ^

note: in instantiation of function template specialization
      'make_obj<const char *>' requested here
    auto s = make_obj("hello");
             ^

尝试做

make_obj("hello");
作为例子。

如何只允许

make_obj
访问
Obj
的价值构造函数?

c++ templates c++11 friend
2个回答
57
投票

你需要一些前向声明:

template <typename T>
class Obj;

template <typename T>
Obj<T> make_obj(T t);

template <typename T>
class Obj {
private:
    T & t;
    Obj (T & t) : t(t) { }
    Obj() = delete;

    friend Obj make_obj<T>(T t);
};

template <typename T>
Obj<T> make_obj(T t) { 
    return Obj<T>(t);
}

实例

顺便说一句:我不认为你真的想要

T & t;
作为你班级的成员变量。可能
T t;
是更好的选择;)


7
投票

使用自动返回类型语法,你只需要前向声明函数就可以了。这是一个例子

template <typename T>
auto make_obj(T t);

template <typename T>
class Obj {
private:
    T & t;
    Obj (T & t) : t(t) { }
    Obj() = delete;

    friend auto make_obj<T>(T t);
};

template <typename T>
auto make_obj(T t) {
    return Obj<T>{t};
}

int main() {
    make_obj(1);
    return 0;
}

https://ideone.com/3k86gx

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