Indiana Unversity logo[ConceptGCC]

ConceptGCC :

Unable to write a concept map template with a requires clause specifying a type derived from a class template

From: Tom Honermann (tom.honermann_at_[hidden])
Date: 2007-06-22 05:10:05


I've been trying to use conceptgcc-BoostCon on Linux/x86 to write a
concept map template to apply to types that derive from a base template
class, but not having much luck...

Consider this code:

    #include <concepts>

    concept C<typename T> {}

    template<typename T>
    struct Base {};

    // template concept map to apply to any type that is derived from
    Base<T>
    template<typename T, std::DerivedFrom<Base<T>> TDerived>
    concept_map C<TDerived> {}

    struct Derived : public Base<char> {};

    template<C T>
    void Foo(T t) {}

    int main() {
        Derived d;
        Foo(d);
        return 0;
    }

Compiling this results in the following error:

    file.cpp:10: error: template parameters not used in partial
    specialization:
    file.cpp:10: error: `T'
    file.cpp: In function `int main()':
    file.cpp:19: no matching function for call to `Foo(Derived&)'
    file.cpp:15: note: candidates are: void Foo(T) [with T = Derived]
    <where clause>
    file.cpp:19: note: no concept map for requirement `C<Derived>'
    file.cpp:3: note: concept `C<Derived>' syntactically matches
    file.cpp:19: note: if the concept semantics are met, write a
    concept map:
    concept_map C<Derived> {};

I have been unable to identify any section in n2193 that specifies that
all template parameters must be referenced within the concept-id
concept_map is mapping. It seems to me that use of all template
parameters by a combination of the requires clause and concept-id should
be supportable, so I'm not sure if this is an unimplemented feature in
conceptgcc, a bug, a design/specification issue, or a misunderstanding
on my part.

I've tried working around the unused template parameter issue by using
another class to perform the lookup.

    template<typename T, std::DerivedFrom<Base<T>> TDerived>
    struct MyDerivedFrom {
        typedef TDerived type;
    };
    template<typename T, typename TDerived>
    concept_map C<typename MyDerivedFrom<T, TDerived>::type> {}

This does avoid the unused template parameters error, however the code
still fails to compile.

    file.cpp: In function `int main()':
    file.cpp:23: no matching function for call to `Foo(Derived&)'
    file.cpp:19: note: candidates are: void Foo(T) [with T = Derived]
    <where clause>
    file.cpp:23: note: no concept map for requirement `C<Derived>'
    file.cpp:3: note: concept `C<Derived>' syntactically matches
    file.cpp:23: note: if the concept semantics are met, write a
    concept map:
    concept_map C<Derived> {};

For my own code, I was able to work around this by forcing the template
base class to derive from a non-template base class and then declare the
concept_map to apply to any type that derives from the non-template base
class.

    struct Base {};

    template<typename T>
    struct TemplateBase : public Base {};

    template<std::DerivedFrom<Base> T>
    concept_map C<T> {}

Tom.