tuplet icon indicating copy to clipboard operation
tuplet copied to clipboard

Document a nice advantage of tuplet over std::tuple - allowed to be passed as non-type template argument since it's consexpr

Open Tal500 opened this issue 6 months ago • 0 comments

Thanks for this awesome one header project! Hope that this project is still alive :-)

I was trying to find a solution for a problem that wasn't described in this project README, but this problem is solved. I believe that these issue with std::tuple should be stated in the README.

For terrible reasons, since std::tuple isn't trivially copyable, std::tuple couldn't be accepted as a non-type template argument. But this library has no such problem, and it is allowed!

What I mean is that the following code is legal:

template <tuplet::tuple<int, int> t>
consteval int func_tuplet() {
    return get<1>(t) + 1;
}

void test_tuplet() {
    constexpr tuplet::tuple t {1, 2};
    func_tuplet<t>();
}

While this code fails to compile:

template <std::tuple<int, int> t>
consteval int func_std() {
    return std::get<1>(t) + 1;
}

void test_std() {
    constexpr std::tuple t {1, 2};
    func_std<t>();
}

GCC calls this std::tuple<int, int> as "incomplete type", following the explanation I mentioned before (from compiler explorer, x86-64 GCC, with the flag -std=c++23):

<source>:1504:32: error: invalid use of incomplete type 'class std::tuple<int, int>'
 1504 | template <std::tuple<int, int> t>
      |                                ^
In file included from /opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/utility:69,
                 from <source>:6:
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/stl_pair.h:90:11: note: declaration of 'class std::tuple<int, int>'
   90 |     class tuple;
      |           ^~~~~
<source>: In function 'void test_std()':
<source>:1510:33: error: class template argument deduction failed:
 1510 |     constexpr std::tuple t {1, 2};
      |                                 ^
<source>:1510:33: error: no matching function for call to 'tuple(int, int)'
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/stl_pair.h:90:11: note: candidate: 'template<class ...> tuple()-> std::tuple< <template-parameter-1-1> >'
   90 |     class tuple;
      |           ^~~~~
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/stl_pair.h:90:11: note:   template argument deduction/substitution failed:
<source>:1510:33: note:   candidate expects 0 arguments, 2 provided
 1510 |     constexpr std::tuple t {1, 2};
      |                                 ^
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/stl_pair.h:90:11: note: candidate: 'template<class ...> tuple(std::tuple< <template-parameter-1-1> >)-> std::tuple< <template-parameter-1-1> >'
   90 |     class tuple;
      |           ^~~~~
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/stl_pair.h:90:11: note:   template argument deduction/substitution failed:
<source>:1510:33: note:   mismatched types 'std::tuple< <template-parameter-1-1> >' and 'int'
 1510 |     constexpr std::tuple t {1, 2};
      |                                 ^
<source>:1511:16: error: no matching function for call to 'func_std<t>()'
 1511 |     func_std<t>();
      |     ~~~~~~~~~~~^~
<source>:1505:15: note: candidate: 'template<<typeprefixerror>t> consteval int func_std()'
 1505 | consteval int func_std() {
      |               ^~~~~~~~
<source>:1505:15: note:   template argument deduction/substitution failed:
Compiler returned: 1

More generally, std::tuple cannot be a consexpr. Here is the cpp test function:

void test_std_tuple_constexpr() {
    constexpr std::tuple<int, int> t {1, 2};
}

And here is the same GCC output:

<source>: In function 'void test_std_tuple_constexpr()':
<source>:1495:36: error: variable 'constexpr const std::tuple<int, int> t' has initializer but incomplete type
 1495 |     constexpr std::tuple<int, int> t {1, 2};
      |                                    ^
Compiler returned: 1

Tal500 avatar Dec 16 '23 17:12 Tal500