Quantcast
Channel: Active questions tagged gcc - Stack Overflow
Viewing all articles
Browse latest Browse all 22102

GCC stricter than Clang for resolving dependent names for concepts

$
0
0

I've been playing around with C++20 concepts and ran into an issue with my GCC 9.4 compiler, which I ultimately want to support. I created this minimal reproducible example to showcase the problem:

#include <iostream>#include <type_traits>template <typename T, typename Type>concept IsSame = std::is_same_v<T, Type>;template <typename Scalar>class MyClass {   public:    template <typename T>    using ScalarT = T;    template <typename T>    requires IsSame<T, typename MyClass<Scalar>::template ScalarT<double>>    static void print(const T& b);};// Compilation depends on compilertemplate<typename Scalar>template<typename T>requires IsSame<T, typename MyClass<Scalar>::template ScalarT<double>>void MyClass<Scalar>::print(const T& t) {    std::cout << std::fixed << t << " as Scalar is " << std::fixed << static_cast<Scalar>(t) << std::endl;}int main() {    MyClass<int>::print(6.0);    return 0;}

GCC 9.4 (with -std=c++2a -fconcepts) and the more recent GCC 14.2 (with -std=c++20) complain that:

<source>:334:6: error: no declaration matches 'void MyClass<Scalar>::print(const B&)'  334 | void MyClass<Scalar>::print(const B& b) {      |      ^~~~~~~~~~~~~~~<source>:327:17: note: candidate is: 'template<class Scalar> template<class T>  requires  IsSame<T, double> static void MyClass<Scalar>::print(const T&)'  327 |     static void print(const T& b);      |                 ^~~~~<source>:320:7: note: 'class MyClass<Scalar>' defined here  320 | class MyClass {

However, both GCC compilers are ok with defining the function inline, as:

    template <typename T>    requires IsSame<T, typename MyClass<Scalar>::template ScalarT<double>>    static void print(const T& t) {        std::cout << std::fixed << t << " as Scalar is " << std::fixed << static_cast<Scalar>(t) << std::endl;    }

or

    template <typename T>    requires IsSame<T, ScalarT<double>>    static void print(const T& t) {        std::cout << std::fixed << t << " as Scalar is " << std::fixed << static_cast<Scalar>(t) << std::endl;    }

Clang 19.1 (with -std=c++2a) has no issue, and prints 6.000000 as Scalar is 6.

I know I could also do the following:

template <IsSame<ScalarT<double>> T>    static void print(const T& t) {        std::cout << std::fixed << t << " as Scalar is " << std::fixed << static_cast<Scalar>(t) << std::endl;    }

But this has the same issue with GCC, where moving the implementation outside the class does not work:

template<typename Scalar>template<IsSame<typename MyClass<Scalar>::template ScalarT<double>> T>static void MyClass<Scalar>::print(const T& t) {    std::cout << std::fixed << t << " as Scalar is " << std::fixed << static_cast<Scalar>(t) << std::endl;}

Viewing all articles
Browse latest Browse all 22102

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>