The following is a toy example
The class student
has a std::array<char, 15>
called name
and an integer age
. A student has a member function called encode
that calls a global template function encode
using name.size()
as a template parameter.
The code is shown below:
//main.cpp
#include <iostream>
#include <array>
template <unsigned long num1>
unsigned long encode(unsigned long num2){
return num1 + num2;
}
struct student {
std::array<char, 15> name;
int age;
student(const std::array<char, 15>& name, int age):
name(name),
age(age)
{}
unsigned long encode(){
return ::encode<name.size()>(age);
}
};
int main(){
std::array<char, 15> name = {"Tim"};
student Tim(name, 17);
std::cout << Tim.encode();
}
However, this produces the following compiler error
>g++ main.cpp -std=c++11
main.cpp: In member function 'long unsigned int student::encode()':
main.cpp:22:43: error: use of 'this' in a constant expression
22 | return ::encode<name.size()>(age);
| ^
main.cpp:22:45: error: no matching function for call to 'encode<((student*)this)->student::name.std::array<char, 15>::size()>(int&)'
22 | return ::encode<name.size()>(age);
| ~~~~~~~~~~~~~~~~~~~~~^~~~~
main.cpp:9:15: note: candidate: 'template<long unsigned int num1> long unsigned int encode(long unsigned int)'
9 | unsigned long encode(unsigned long num2){
| ^~~~~~
main.cpp:9:15: note: template argument deduction/substitution failed:
main.cpp:22:45: error: use of 'this' in a constant expression
22 | return ::encode<name.size()>(age);
| ~~~~~~~~~~~~~~~~~~~~~^~~~~
main.cpp:22:42: note: in template argument for type 'long unsigned int'
22 | return ::encode<name.size()>(age);
Is it required I do ::encode<15>(age)
to solve this problem, because I though one of the major benefits of a std::array
is being able to carry a size rather than having to store the size in some extra variable (or hardcoding the size).
g++ version: 14.1.0
I dislike including the <tuple>
header just to use std::tuple_size_v
.
I think you can also express the same using
return ::encode<decltype(name){}.size()>(age);
decltype(name)
gives you the type, without the need of the this
pointer{}
creates an instance.size()
gives you the size of that instanceSince this is constexpr, this evaluates to 15 at compile time and there's no actual overhead for the creation of the temporary instance.