Может ли компилятор исключить тела функций, которые взяты по адресу, но никогда не вызваны? - PullRequest
2 голосов
/ 23 февраля 2020

Справочная информация


Рассмотрим упрощенную реализацию std::any (не относящиеся к делу детали) и некоторый код, который его использует:

namespace std {
  namespace details {
    // Each instance of this function template has a different address
    template <typename T>
    const char *dummy_function() { return __PRETTY_FUNCTION__; }

    template <typename T> void *construct(T &&);
    void destroy(void *storage, const char *(*type_identifier)());
  }

  class any {
    const char *(*type_identifier)();
    void *storage;

  public:
    template <typename Arg>
    any(Arg &&arg)
      : type_identifier(&details::dummy_function<decay_t<Arg>>)
      , storage(details::construct(forward<Arg>(arg))) {}

    template <typename Arg>
    any &operator=(Arg &&arg) {
      details::destroy(storage, type_identifier);
      type_identifier = &details::dummy_function<decay_t<Arg>>;
      storage = details::construct(forward<Arg>(arg));
    }

    template <typename T>
    friend T *any_cast(any *source) {
      if (source && source->type_identifier == &dummy_function<T>)
        return static_cast<T *>(source->storage);
      return nullptr;
    }
  };
}
#include <any>

// Code that compares any::type_identifier a lot but never calls through it
std::any any = 42;
assert(std::any_cast<int>(&any) != nullptr);
assert(std::any_cast<double>(&any) == nullptr);

any = std::string("Hello");
assert(std::any_cast<std::string>(&any) != nullptr);
assert(std::any_cast<std::vector<char>>(&any) == nullptr);

Если оптимизирующий компилятор может доказать, что std::details::dummy_function<T> никогда не вызывается каким-либо образом по всей программе, разрешено ли компилятору не включать тело функции std::details::dummy_function<T> (вместе с не имеющими ссылки __PRETTY_FUNCTION__ s) для любого T в результате компиляции (и даже, возможно, сделать их адреса произвольными целыми числами размером с указатель, которые просто гарантированно различаются, но в противном случае могут даже не быть действительными адресами памяти)?

(Или могут даже адреса не гарантироваться быть отличным для различных T s, что, к сожалению, означает, что моя реализация неверна с самого начала?)

...