Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't specialize formatter for templated ranged class #751

Closed
drrlvn opened this issue May 29, 2018 · 2 comments
Closed

Can't specialize formatter for templated ranged class #751

drrlvn opened this issue May 29, 2018 · 2 comments

Comments

@drrlvn
Copy link
Contributor

drrlvn commented May 29, 2018

If I include fmt/ranges.h I cannot specialize fmt::formatter for my type that is ranged and templated.
Say I have this class:

template<typename T>
class Foo {
public:
    ...
    const_iterator begin() const { ... }
    const_iterator cbegin() const { ... }
    ...
};

When trying to provide a specialization of fmt::formatter for this class:

template<typename T>
struct formatter<Foo<T>> {
    ...
};

I get an ambiguous template instantiation error because of the specialization in fmt/ranges.h:

include/fmt/core.h:529:56: error: ambiguous template instantiation for ‘struct fmt::v5::formatter<Foo<int>, char, void>’
     typename Context::template formatter_type<T>::type f;
                                                        ^
In file included from ...:
include/fmt/ranges.h:199:8: note: candidates are: ‘template<class RangeT, class Char> struct fmt::v5::formatter<RangeT, Char, typename std::enable_if<fmt::v5::internal::is_range<T>::value>::type> [with RangeT = Foo<int>; Char = char]’
 struct formatter< RangeT, Char,
        ^~~~~~~~~~~~~~~~~~~~~~~~
     typename std::enable_if<fmt::internal::is_range<RangeT>::value>::type> {
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ...:
foo.cpp: note:                 ‘template<class T> struct fmt::v5::formatter<Foo<T> > [with T = int]’
     struct formatter<Foo<T>> {
            ^~~~~~~~~~~~~~~~~

As a workaround I can force fmt::internal::is_range to be false:

namespace fmt::internal {

template<typename T>
struct is_range<Foo<T>> : std::false_type {};

} // namespace fmt::internal

But obviously I would want to avoid defining anything in an internal namespace.

@vitaut
Copy link
Contributor

vitaut commented Jun 4, 2018

I think it's reasonable to make is_range part of the public API and move it to the fmt namespace. Could you submit a PR?

@drrlvn
Copy link
Contributor Author

drrlvn commented Jun 5, 2018

Sure, submitted #759.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants