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

The template keyword is needed to call tuple.get_ref() and union.get_ref() etc #124

Open
danakj opened this issue Dec 18, 2022 · 3 comments
Labels
design Design of the library systems as a whole, such as concepts

Comments

@danakj
Copy link
Collaborator

danakj commented Dec 18, 2022

This is awkward...

auto tuple = ...;
tuple.get_ref<0>();  // no :(
tuple.template get_ref<0>();  // yes :(

Not only this but the compiler errors on MSVC and GCC complain about the () missing arguments (cuz we have get_ref() methods on some types that take an argument?) instead of complaining about missing template. Only Clang gets this right..

I wish we could pass the index as a parameter but I don't think that we can, we have to walk up N base classes in tuple, and the methods can't be consteval or anything like that.

Do we move to a global get_ref? :/ That's really unlucky if so. And it's not needed for vec/array/slice/indexing things.

@danakj
Copy link
Collaborator Author

danakj commented Dec 18, 2022

Some possible thoughts from discussion with @quisquous.

  1. Another user defined literal that resolves to a std::integral_constant<size_t, I> if that's possible. Something like:
my_tuple.get_ref(5_t);

But it's a bit unlucky to need to use another type like that. But being able to deduce the template parameter is required to avoid the template keyword IIUC.

  1. Drop the template parameter, use a big switch.
const auto& get_ref(size_t i) const& noexcept {
  switch (i) {
    case 0: return get_ref_impl<0>();
    case 1: return get_ref_impl<1>();
    case 2: return get_ref_impl<2>();
    ...
    case 100: return get_ref_impl<100>();
    ...
    case SIZE_T_MAX: return get_ref_impl<SIZE_T_MAX>();
  }
}

Which could be generated by a recursive macro easily enough, I think. It generates quite a bit of code though.

  • Could it be moved out of the header file? It would need to be type-agnostic for the Tuple itself, and just a helper that is called from the header.
  • How many Tuple elements would it really need to support? Is 100 good enough? Do we care to support code generators with Tuples of 10000s of types in them should such a thing exist?

@danakj danakj added the design Design of the library systems as a whole, such as concepts label Dec 18, 2022
@danakj
Copy link
Collaborator Author

danakj commented Dec 29, 2022

The switch idea probably doesn't work. It would have to be evaluated as constexpr in order to return different types. So we could if constexpr () else if constexpr () ... but the input is a runtime value so it can't be constexpr evaluated, and we can't overload on it. It would need to instead be a type, which the 5_t approach takes.

Though I wonder if we can make a type that consteval-constructs from a number literal? Looks like no. I was hoping it would deduce the template value from the constructor argument.

template <int I>
struct NumType {
    consteval NumType(int i) {}  // Provides CTAD-based implicit conversion.
    static constexpr int value = I;
};

int f(NumType<0>) { return 0; }
int f(NumType<1>) { return 1; }

int main() {
    return f(1);
}
<source>:15:12: error: call to 'f' is ambiguous
    return f(1);
           ^

Function parameters can't be constexpr so it can't tell that the value is a literal.

template<int I>
NumType(int i) -> NumType<i>;
<source>:11:27: error: non-type template argument is not a constant expression
NumType(int i) -> NumType<i>;
                          ^

@danakj
Copy link
Collaborator Author

danakj commented Dec 29, 2022

See also https://stackoverflow.com/questions/37231651/implicitly-convert-number-to-integral-const which does this for a free function.. with macros. Not what we want.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
design Design of the library systems as a whole, such as concepts
Projects
None yet
Development

No branches or pull requests

1 participant