2

我有一堂课T,我想让这段代码不编译:

void PassByValue(T);

但允许所有这些:

void PassByRefernce(T&);
void PassByPointer(T*);

注意:我希望它是非法的(即生成编译错误)来声明一个T按值取值的函数,即使该函数从未使用或定义过。


编辑:请注意,以下是完全有效的 C++:

class T {
  public:
    T() {}
  private:
    // Prevent copy/assignment
    T(const T&);
    T& operator=(const T&);
};

void Fn(T);  // I want this line to error, even if the function is never used.

int main() { return 0; } 
4

2 回答 2

4

严格来说这不是可能的(见下文),您能做的最好的事情就是通过使此类功能不可复制来使此类功能无法使用/无法定义T

这是通过删除复制ctor来完成的,如下所示:

class T
{
    T(const T&) =delete;
    T& operator=(const T&) =delete;
    .....
};

如果您不能使用 C++11,则将这些声明设为私有也会产生相同的效果:

class T
{
public:
    .....
private:
    T(const T&);
    T& operator=(const T&);
};

不需要实施。

这样,类就不能从另一个实例接收状态,因此传递给函数的唯一方法是通过间接(通过引用或指针)。


当然,这不会“解决”(字面上)原始问题,因为声明诸如

void func(T);

还是有可能的。但是,不可能调用该函数,因此 T 的安全性被授予。

不幸的是,对于今天如何定义 C++ 语言,不存在“干净”的解决方案,因为像这样的代码

struct A;
void func(A);

必须编译。

尽管代码本身什么都不做(它只是声明了一些符号),但没有什么struct A;要说的关于A语义的事情。要拒绝func我们必须在包含或包含完整A声明的翻译单元(CPP 文件)中的声明(这样我们就可以知道不可能有副本),那必须 - 在这一点上 - 在 func 之前。但这并不一定发生在包含上述片段的所有翻译单元中。

有些语言可以做到这一点:想想 D,只是为了留在“系统语言域”中。但是 D - 允许“在完全声明之前使用” - 不是“包含源”而是“导入模块”(编译器可以访问完整的定义)支持迭代翻译(如果某些内容尚未定义并且稍后编译器定义返回“优化”并重复,直到它“收敛”为一致的代码,或者如果发现不一致则拒绝该代码)。并且 - 由于其“导入机制”和语义/句法分离,无法链接到(大部分)C++,而只接受 C 编译的库或 objs。(并且需要标题的 C 到 D 翻译!)

C++ 翻译通行证会演变成类似 D 的通行证吗?很难说。非常不可能,而必须保留 C“包含模型”的 C 向后兼容性。

于 2012-07-11T19:48:38.507 回答
0

你有两个选择。要么将复制构造函数设为私有,要么将 T 设为抽象类。

于 2012-07-11T19:49:22.033 回答