Я столкнулся с интересным шаблоном в библиотеке concontexpr .
Согласно readme, идея заключается в том, что, учитывая функцию автоматического возврата типа, объявленную вперед, тип возврата может ' не может быть выведено до фактического определения функции, и это позволяет некоторым SFINAE magi c.
Я думал, что эта функция языка может быть полезна для нескольких других идей, и провел некоторые эксперименты с ней, и это выглядит например, g cc и clang ведут себя по-разному, когда функция не является шаблоном: g cc работает так же, в то время как clang сообщает об ошибке.
И на основании того, что показывает сообщение об ошибке clang, возможно, это не должно работать даже для шаблона?
Итак, вопросы:
- Является ли часть шаблона (разрешенная как clang, так и g cc) разрешенной стандартом?
- какой компилятор верен в не шаблонной версии?
Упрощенный код (также для godbolt ):
struct S {};
constexpr auto f1();
template <typename T>
constexpr auto f2(T);
// compilation error with clang:
// function with deduced return type cannot be used before it is defined
template <typename T, typename = decltype(f1())>
void test1_1() {}
template <typename T>
void test1_1() {}
// compiles with clang, even if f2 will never be defined
template <typename T, typename = decltype(f2<T>(T{}))>
constexpr int test1_2(int) { return 1; }
template <typename T>
constexpr int test1_2(float) { return 2; }
/////////////////
int g1_2() {
return test1_2<S>(0);
}
constexpr auto f1() { return 1; }
// comment-uncomment this:
// the value returned by g2_@ will change
// /*
template <typename T>
constexpr auto f2(T) {
return 2;
}
// */
// can be defined here
template <typename T, typename = decltype(f1())>
void test2_1() {}
int g2_2() {
return test1_2<S>(0);
}
Примечание: Первоначально я также упоминаю Если бы он вел себя по-разному с друзьями, и, похоже, он работает без автоматического возврата - это были ошибки пользователя с моей стороны.