clang и g cc не согласны при вызове функции-члена stati c constexpr для типа, выведенного из ссылочного типа с l-значением - PullRequest
2 голосов
/ 11 февраля 2020

Существует различие в поведении clang и g cc в контексте constexpr функции-члена для ссылок на l-значения, которые уже обсуждались здесь: stackoverflow / question / 57779870

Я расширил это до статических c вызовов функций для типа, который выводится из эталонного объекта l-value, и следующее все еще не работает в clang:

#include <type_traits>

// Dummy class with static constexpr member function
class MyClass {
public:
static constexpr bool check(int id){return true;}
};

template<int id, typename someT>
static constexpr bool doWithDeduction(someT& argument){
    return std::remove_reference_t<someT>::check(id);
}

// Replaced argument type by a dummy int type, argument is not used anyway
template<int id, typename someT>
static constexpr bool doWithDeduction(int& argument){
    return std::remove_reference_t<someT>::check(id);
}


// No function arguments! this works!
template<int id, typename someT>
static constexpr bool doSomething(){
    return std::remove_reference_t<someT>::check(id);
}

// wrapper to pass by ref
void wrap(MyClass& arg, int& i) {

    // works with gcc & clang
    static_assert(doSomething<1, decltype(arg)>(), "assert");

    // The following are not integral constexpr according to clang

    // This is what I want (type deduction for arg)
    static_assert(doWithDeduction<1>(arg), "assert");

    // Even when the type is not deduced but given here, this does not compile in clang
    static_assert(doWithDeduction<1, std::remove_reference_t<decltype(arg)>>(arg), "assert");

    // As soon as I pass somting(here int) as reference, clang complains about integral constant expressions
    static_assert(doWithDeduction<1, decltype(arg)>(i), "assert");
}

int main() {
    int i{1};
    MyClass myObject{};
    wrap(myObject, i);
}

Этот пример также доступен здесь: online_example godbolt Я использую g cc 9.2.0 и clang 9.0.1. -std = c ++ 17 (или -std = c ++ 14)

Может кто-нибудь объяснить, почему не работает даже последний вызов?
И какое поведение желательно?

1 Ответ

0 голосов
/ 13 февраля 2020

Я немного озадачен тем, что g cc делает здесь. Ваши static_assert s не снабжены значениями времени компиляции. Для clang вполне разумно отклонить код, поскольку он кажется ошибочным. Я имею в виду - wrap не является constexpr и не получает constexpr значений. Вы не можете ожидать, что его содержимое будет оценено во время компиляции.

...