Доступ к статическому элементу constexpr шаблона в виде константного выражения - PullRequest
0 голосов
/ 14 мая 2018

Я пытаюсь получить доступ к статическому члену constexpr шаблона класса в виде константного выражения, где член имеет тот же тип, что и определяемый класс. MSVC и clang, похоже, душат этот простой пример:

#include <iostream>

struct A
{
    static A const DEFAULT;

    constexpr A(int value = {}) : _value{ value } {}

    constexpr operator int() const { return _value; }

    int const _value;
};

constexpr A const A::DEFAULT{};

template<typename = void>
struct B_impl
{
    static B_impl const DEFAULT;

    constexpr B_impl(int value = {}) : _value{ value } {}

    constexpr operator int() const { return _value; }

    int const _value;
};

template<typename T>
constexpr B_impl<T> const B_impl<T>::DEFAULT{};

using B = B_impl<>;

template<int N>
constexpr int foo() { return N; }

int main(int, char**) noexcept
{
    std::cout << "A: " << foo<A::DEFAULT>() << "\n"; // IntelliSense hates this
    std::cout << "B: " << foo<B::DEFAULT>() << "\n"; // VC++ and clang die here:
    // MSVC error:  C2975  'N': invalid template argument for 'foo', expected compile-time constant expression
    // clang error:  note: candidate template ignored: invalid explicitly-specified argument for template parameter 'N'
    return 0;
}

gcc принимает как A, так и B как константные выражения. MSVC и clang (demo) принимают A в качестве константного выражения и согласны с B, если я не попытаюсь использовать его в качестве константного выражения, а затем произойдет сбой.

Вся причина, по которой я пытаюсь использовать шаблон здесь, заключается в достижении встроенных переменных без применения C ++ 17, поскольку это предназначено для использования в заголовочном файле.

В этом урезанном примере я мог бы вместо этого использовать статическую функцию constexpr, которая хранит значение constexpr, а затем возвращает значение (поскольку статические переменные constexpr запрещены в функциях constexpr, поэтому я не мог вернуться по ссылке). Реальный код немного сложнее, но я его не демонстрировал, потому что он скрывает основную проблему ( gcc demo ). Я на самом деле пытаюсь сохранить массив значений ( определяемого типа , поэтому встроенные определения constexpr невозможны) с именованными ссылками на эти значения, все из которых должны быть статическими constexpr.

Опять же, это работает на всех трех компиляторах , если я опускаю шаблон , что я не хочу делать, так как это в заголовке, и я пытаюсь , чтобы избежать взлома ODR.

Ошибка MSVC и clang в отклонении этой шаблонной версии, или gcc пропускает что-то, что не должно быть возможным?

...