Существует различие в поведении 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)
Может кто-нибудь объяснить, почему не работает даже последний вызов?
И какое поведение желательно?