如何防止类型被声明为值参数?

时间:2012-07-11 19:27:28

标签: c++ compiler-errors pass-by-value

我有一个类T,我想让这段代码不能编译:

void PassByValue(T);

但允许所有这些:

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

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


编辑:请注意以下是完全有效的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; } 

2 个答案:

答案 0 :(得分:4)

这不是严格可能的(见下文),你可以做的最好的事情就是通过使T不可复制来使这种功能无法使用/无法确定。

通过删除复制文件来完成,如下所示:

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文件)内(以便我们可以知道不可能复制),必须 - point - 优先于func之一。但是,在包含上述代码段的所有翻译单元中,这种情况并非必要。

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

C ++翻译版会逐渐演变为类似D的翻译吗?很难说。在必须保留C“包含模型”的C向后兼容性时非常不可能。

答案 1 :(得分:0)

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