是否有可能在编译时强制执行两个派生 类 总是 return 不同的覆盖函数值?

Is it possible to enforce, at compile time, that two derived classes would always return different values for an overriding function?

是否可以在编译时强制执行以下内容:

class B {
public:
    virtual constexpr const char* getKeyStr() const = 0;
};

class D1 : public B {
public:
    constexpr const char* getKeyStr() const override { return "D1"; }
};

class D2 : public B {
public:
    constexpr const char* getKeyStr() const override { return "D2"; }
};

...但是下面不是?我们不希望 D1D2 到 return 相同的密钥字符串:

class B {
public:
    virtual constexpr const char* getKeyStr() const = 0;
};

class D1 : public B {
public:
    constexpr const char* getKeyStr() const override { return "D1"; }
};

class D2 : public B {
public:
    constexpr const char* getKeyStr() const override { return "D1"; } // can we error out here at compile time?
};

澄清:

  1. 我在这个例子中只展示了两个派生的 classes,但我想要实现的是 post 这个对任意数量的派生 [=42] 的约束=]es.

  2. 要解决的潜在问题:我正在考虑一个serializing/deserializing应用程序,其中每个具有相同基数class的对象将能够生成一个textual/string 将其自身表示写入文件,并且当返回该字符串(我们称之为内容字符串)时,将能够重建相应的数据。

    在反序列化过程中,应用程序代码应该能够从内容字符串的关键部分(我们称之为关键字符串)判断出应该重构哪个派生对象。因此,密钥字符串对于每个派生的 class 都必须是唯一的。我知道 type_info::name 可能是唯一的,但它不可定制(或独立于编译器?)。

  3. 关于getKeyStr()函数(对应上面提到的key-string),对于同一个derived的所有objects总是return同一个字符串class.

是的,你可以在编译时检查D1getKeyStrD2返回的"strings"是否不同。

首先提供一个在编译时比较2const char *的函数:

constexpr bool different(const char *x, const char *y)
{
  while(*x != '[=10=]' )
    if (*x++ != *y++) return true;

  return *y != '[=10=]'; 
}

然后比较返回值:

// this will trigger, if returned strings are the same.
static_assert( different(D1{}.getKeyStr(), D2{}.getKeyStr()) );  

编辑:正如@Jarod42 指出的那样,string_view 比较是 constexpr,因此比较函数可以写得更简单:

constexpr bool different(const char * x, const char * y)
{
    return std::string_view{x} != std::string_view{y};
}

这是 demo.

如果你可以得到所有 Derived 类 的列表,你可能会这样做:

template <typename... Ts>
bool have_unique_keys()
{
    std::string_view keys[] = {Ts{}.getKeyStr()...}; // requires constexpr default constructor
                                                     // static method might be more appropriate
    std::sort(std::begin(keys), std::end(keys)); // constexpr in C++20
    auto it = std::adjacent_find(std::begin(keys), std::end(keys));
    return it != std::end(keys);
}

static_assert(have_unique_keys<>(D1, D2, D3));