如果(并且仅当)它具有复制构造函数,如何复制对象?

时间:2018-06-14 05:32:55

标签: c++ copy-constructor memoization

上下文:我正在尝试记住模板类的对象。现在,该类是一个深度嵌套的数据结构,充满了独特的指针,因此没有复制构造函数(据我所知,因此不可能缓存)。但是,将来,如果有可用的复制构造函数,我想允许进行memoization。我尝试了以下代码:

// some function here... {
  static std::unordered_map<State, Result> cache;

  return [c, ToValue](State state) {
      if (cache.find(state) != cache.end()) {
        std::cout << "retrieving Literal from cache\n";
        if (std::is_copy_constructible<Result>::value) {
          return cache[state];
        }
      }
      // calculate and return a Result

此代码无法编译,因为Result没有复制构造函数。有没有办法解决这个问题?谷歌非常无益。

2 个答案:

答案 0 :(得分:1)

正如其他人所评论的那样,问题是定义不明确而且有点困惑,但你是否需要实际复制一个对象才能缓存它?

实际上,没有。您可以使用std::shared_ptr在创建者,任何使用者和缓存之间共享对象的所有权。如果没有别的,如果您的对象是一个复杂的对象,这会更有效。它也适用于任何类型的对象,可复制或不可复制。

示例(我将使用单词Key而不是State,因为我希望这是显而易见的原因。)

鉴于这些声明:

class MyKey
{
    // ....
};

class MyCacheableObject
{
    // Constructor
    MyCacheableObject (int a, int b, int c) { ... }
    // ...
};

static std::unordered_map<MyKey, std::shared_ptr<MyCacheableObject>> cache;  // or std::map

您可以执行此操作(请注意,还有其他方法可以制作std::shared_ptr,请参阅here):

std::shared_ptr<MyCacheableObject> CreateCacheableObject (int a, int b, int c)
{
    return std::make_shared<MyCacheableObject> (MyCacheableObject (a, b, c));
}

然后,假设您有一个计划用于稍后从缓存中检索对象的密钥,您可以这样做:

MyKey someKey = ...;
std::shared_ptr<MyCacheableObject> newObject = CreateCacheableObject (1, 2, 3);

// ... setup / use `newObject` in whatever way is appropriate to your use-case 

cache [someKey] = newObject;

当然,您可以通过以下方式从缓存中检索对象(如果它在那里):

auto retrievedObject = cache.find (someKey)
if (retrievedObject != cache.end())
    ...

所以这个问题不是关于一个对象是否可以复制。它是关于(共享)所有权的,std::shared_ptr为你照顾所有这些,你真的不必考虑它。 Oy vay。

有一个现场演示,以显示所有这些都编译,here

答案 1 :(得分:1)

我认为你得到的错误是当对象不是可复制构造时,if constexpr (std::is_copy_constructible<Result>::value) { return cache[state]; } 无法编译。要解决这个问题,你可以写:

public class PassportStamp
    {
        [Key]
        public int Id { get; set; }
        [MaxLength(10, ErrorMessage = "BloggerName must be 10 characters or  less"), MinLength(5)]
        public string BloggerName { get; set; }
        [Required]
        public string Title { get; set; }
        [NotMapped]
        public string BlogCode
        {
            get
            {
                return Title.Substring(0, 1) + ":" + BloggerName.Substring(0, 1);
            }
        }
    }

如果您仍然遇到问题,请发布有错误的MCVE