cppfront icon indicating copy to clipboard operation
cppfront copied to clipboard

[BUG] Can't pass dependent type template argument

Open JohelEGP opened this issue 2 years ago • 3 comments

Title: Can't pass dependent type template argument.

Minimal reproducer (https://cpp2.godbolt.org/z/W1dKeeKso):

f: <T> () std::vector<T::value_type>();
main: () = { }
Commands:
cppfront main.cpp2
clang++18 -std=c++23 -stdlib=libc++ -lc++abi -pedantic-errors -Wall -Wextra -Wconversion -Werror=unused-result -I . main.cpp

Expected result: std::vector<typename T::value_type>.

Actual result and error: std::vector<T::value_type>.

Cpp2 lowered to Cpp1:


//=== Cpp2 type declarations ====================================================


#include "cpp2util.h"



//=== Cpp2 type definitions and function declarations ===========================

template<typename T> [[nodiscard]] auto f() -> auto;
auto main() -> int;


//=== Cpp2 function definitions =================================================

template<typename T> [[nodiscard]] auto f() -> auto { return std::vector<T::value_type>();  }
auto main() -> int{}
Output:
build/main.cpp:18:74: error: template argument for template type parameter must be a type; did you forget 'typename'?
   18 | template<typename T> [[nodiscard]] auto f() -> auto { return std::vector<T::value_type>();  }
      |                                                                          ^
      |                                                                          typename 
/opt/compiler-explorer/clang-trunk-20231004/bin/../include/c++/v1/__iterator/wrap_iter.h:102:21: note: template parameter is declared here
  102 |     template <class _Tp, class _Alloc> friend class _LIBCPP_TEMPLATE_VIS vector;
      |                     ^
1 error generated.

See also:

JohelEGP avatar Oct 04 '23 14:10 JohelEGP

It also seems that it is not possible to declare it in any working way current: typename does not work: (https://cpp2.godbolt.org/z/x4oYsj1E5)

f: <T> () std::vector<typename T::value_type>();
main: () = { }

neither type:

f: <T> () std::vector<type T::value_type>();
main: () = { }

MaxSagebaum avatar May 16 '24 06:05 MaxSagebaum

I'm always going back and forth between these issues. I knew something was missing here. It's Herb's intended resolution.

Would you be solving the ambiguity in template-argument the same as with is-as-expression?

Ack: You beat me to it -- I've been out of computer range but was going to reply saying I expected it would be the same as x is type and x is (value). The parens aren't needed for things like literals, of course.

-- https://github.com/hsutter/cppfront/discussions/628#discussioncomment-6867808

In fact, this issue is linked there, but discussions don't leave tracks on issues.

JohelEGP avatar Oct 04 '24 07:10 JohelEGP

With the fix above, we can potentially allow T& and T&& in Cpp2 type-only contexts to have the same meaning as in Cpp1.

It would allow me to go from

 compound_addition_with: <T, U> concept = // clang-format off
   addition_with<T, U> &&
   requires(inout l: T, d: U) {
-    { l += d } is std::same_as<decltype(l)>;
+    { l += d } is std::same_as<cpp1_ref<T>>;

to

 compound_addition_with: <T, U> concept = // clang-format off
   addition_with<T, U> &&
   requires(inout l: T, d: U) {
-    { l += d } is std::same_as<cpp1_ref<T>>;
+    { l += d } is std::same_as<T&>;

JohelEGP avatar Oct 11 '24 22:10 JohelEGP