C++ 如何防止r值

C++ 如何防止r值,c++,c++11,C++,C++11,我正在创建这样一个函数: void SetItem(const Key &key, const Value &value) { ... } 其中键和值是某种类型 在内部,我想像这样存储这对: std::pair<const Key &, Value> 这将阻止使用r值,但不允许使用const键,我也不喜欢 我有没有办法在保持常量的同时强制键为l值 我可以创建一个r值重载来防止它: void SetItem(Key &&key, co

我正在创建这样一个函数:

void SetItem(const Key &key, const Value &value)
{
    ...
}
其中键和值是某种类型

在内部,我想像这样存储这对:

std::pair<const Key &, Value>
这将阻止使用r值,但不允许使用const键,我也不喜欢

我有没有办法在保持常量的同时强制键为l值

我可以创建一个r值重载来防止它:

void SetItem(Key &&key, const Value &value)
{
     [What do I put here?]
}

感谢

通过对注释的改进,在完全一致的C++11编译器中应该是这样的:

class X{
public:
  void SetItem(Key const& key, Value const& value);
private:
  void SetItem(Key const&&, Value const&) = delete;
};
私有重载将捕获所有密钥值。在重载解析过程中不会进行访问检查,因此我们可以将其置于private下,这样可能的朋友也会在编译时收到一条很好的错误消息,我们=删除它


对于还不支持显式删除函数的编译器,您可以将其保持为未定义状态,但对于可能的朋友,这只会显示为链接器错误。但是,一般观众将收到尼斯'SetItem'是不可访问的编译器错误消息:

结合注释的改进,在完全一致的C++11编译器中应该是这样的:

class X{
public:
  void SetItem(Key const& key, Value const& value);
private:
  void SetItem(Key const&&, Value const&) = delete;
};
私有重载将捕获所有密钥值。在重载解析过程中不会进行访问检查,因此我们可以将其置于private下,这样可能的朋友也会在编译时收到一条很好的错误消息,我们=删除它


对于还不支持显式删除函数的编译器,您可以将其保持为未定义状态,但对于可能的朋友,这只会显示为链接器错误。但是,一般观众将收到尼斯'SetItem'是不可访问的编译器错误消息:

除了@Xeo的答案,你还可以

template<typename T = int> // thanks to Xeo for suggesting the default parameter
void SetItem(Key&& key, const Value& value) {
    static_assert(sizeof(T) == 0, "SetItem cannot be used with temporary values as keys");
}
与未定义函数相比,这种方法的优点是在编译时提供给定的错误消息,而不是得到一个无用的链接器错误


请注意,静态_断言必须依赖于模板参数,以便它在使用时仅出错。否则,编译器可以自由编译它,即使它没有在任何地方被调用,它也会一直出错。

除了@Xeo的答案,您也可以这样做

template<typename T = int> // thanks to Xeo for suggesting the default parameter
void SetItem(Key&& key, const Value& value) {
    static_assert(sizeof(T) == 0, "SetItem cannot be used with temporary values as keys");
}
与未定义函数相比,这种方法的优点是在编译时提供给定的错误消息,而不是得到一个无用的链接器错误


请注意,静态_断言必须依赖于模板参数,以便它在使用时仅出错。否则编译器可以自由编译它,即使没有在任何地方调用它,它也会一直出错。

I don know=delete对非构造函数/析构函数有效所以void SetItemKey&&key,const Value&Value@是的,就是这样。当有人试图调用该函数时,他们会得到一个链接器错误!我希望我能使用=删除;但不幸的是,我使用的是msvc,它不支持它。因此,我将坚持不实现它,并添加一条注释说明这一点。您还应该将其设置为私有。我不知道=delete对非构造函数/析构函数有效所以void SetItemKey&&key,const Value&Value@是的,就是这样。当有人试图调用该函数时,他们会得到一个链接器错误!我希望我能使用=删除;但不幸的是,我使用的是msvc,它不支持它。因此,我将坚持不实施它,并在评论中说明这一点。你还应该将其私有化。拥有l值并不能解决你的终身问题。你是对的,但至少有助于实施它。我希望Key在某个地方是一个静态变量。有一个l值并不能解决你一生中的问题。你是对的,但它至少有助于强制执行它。我希望Key在某个地方是一个静态变量。您也可以使用默认的模板参数IIRC执行此操作。注释掉函数调用,它就可以编译了。@ildjarn VC11也不支持它。所以我们被允许严苛。@ildjarn基本上可以确定预览版中的内容就是发布版中的内容。更好的C++11支持可能会出现在SP1中。Herb Sutter在内部版本中确认了这一点。@Johannes:MSVC10和MSVC11中还没有可变模板:您也可以使用默认的模板参数IIRC来执行此操作。注释掉函数调用,它就可以正常编译。@ildjarn VC11也不支持它。所以我们被允许严苛。@ildjarn基本上可以确定预览版中的内容就是发布版中的内容。更好的C++11支持可能会出现在SP1中。Herb Sutter在内部版本中确认了这一点。@Johannes:MSVC10和MSVC11中还没有可变模板: