pointer non-type template parameter
For 1.:
From [temp.arg.nontype]
1 A template-argument for a non-type template-parameter shall be a converted constant expression (5.20) of the type of the template-parameter. For a non-type template-parameter of reference or pointer type, the value of the constant expression shall not refer to (or for a pointer type, shall not be the address of):
[...]
(1.3) — a string literal (2.13.5),
s2
holds the address of a string literal, and so cannot be used as the parameter here. s1
on the other hand is an array of char
that has been initialized with a string literal, but the value of s1
(when converted to const char*
) doesn't point to the string literal used in the initialization.
For 2.:
Function pointers perhaps? Still I can't say I've ever used a pointer as a non-type parameter.
Is passing of a function pointer through a class type in non-type template parameter allowed in C++20?
Which compiler is correct here?
Clang is correct, the code as written is valid.
GCC not handling that specific case is a known issue.
Passing a function pointer as non-type template parameter
template<class T, T t>
struct constant_t:std::integral_constant<T,t>{
constexpr operator T()const { return t; }
constexpr constant_t(){}
};
#define TYPEDARG(...) \
typename std::decay<decltype(__VA_ARGS__)>::type, \
__VA_ARGS__
Now constant_t<TYPEDARG(foo)>
is a type whose instances can be invoked if foo
is a non-overloaded function and they call foo
.
In c++17 this becomes:
template<auto x>
using constant_t=std::integral_constant<std::decay_t<decltype(x)>,x>;
and use is simply constant_t<foo>
, without all that extra noise.
template<class Fn, class R, class... Args>
R test(Args&&... args) {
return Fn{}(std::forward<Args>(args)...);
}
int foo( int a, int b ) { return a+b; }
int r = test< constant_t<TYPEDARG(foo)>, int, int, int >( 3, 4 );
Pointer to (data) member as non-type template parameter for instance with automatic storage duration / without linkage
Is the compiler (by direct or indirect, e.g. the above, standard requirements) required to sort this out by itself, storing only (compile-time) address offsets between the members, rather than actual addresses?
Pretty much. It's an "offset" even outside of a compile time context. Pointers to members are not like regular pointers. They designate members, not objects. That also means that the verbiage about valid pointer targets does not relate to pointer-to-members.
That's why to produce an actual lvalue out of them, one must complete the picture with something that refers to an object, such as we do in this->*counter
. If you were to try and use this->*counter
where a constant expression is required, the compiler would have complained, but it would have been about this
, and not counter
.
Their distinct nature is what allows them to uncondionally be compile time constants. There's no object that the compiler must check as a valid target.
syntax variants for function pointer as non type template arg
You are going to declare a non-type template parameter. You can write
template < bool( *ptr )( int, int ) >
void Check()
{
ptr( 1, 1 );
}
Inferring type and class when passing a pointer to data member as a non-type template argument
You can use a helper to get the type of the class and the member from the type of a member pointer:
template <typename T> struct type_from_member;
template <typename Cls,typename M>
struct type_from_member<M Cls::*> {
using class_type = Cls;
using member_type = M;
};
Then you can use auto
and inherit from the helper:
template <auto member> struct Mem : type_from_member<decltype(member)> {};
using B = Mem<&Struct::x>;
static_assert( std::is_same_v<B::member_type,int>);
static_assert( std::is_same_v<B::class_type,Struct>);
Related Topics
Why the Sequence-Operation Algorithms Predicates Are Passed by Copy
I++ Less Efficient Than ++I, How to Show This
Are Dollar-Signs Allowed in Identifiers in C++03
Intersection of Two 'Std::Map'S
Why Are Designated Initializers Not Implemented in G++
_Glibcxx_Use_Cxx11_Abi, Gcc 4.8 and Abi Compatibility
Detect When Network Cable Unplugged
Does Gdi+ Have Standard Image Encoder Clsids
How to Implement Tesseract to Run with Project in Visual Studio 2010
How to Get the Starting/Base Address of a Process in C++
How to Name This Key-Oriented Access-Protection Pattern
If Constexpr - Why Is Discarded Statement Fully Checked
Why Do We Even Need the "Delete[]" Operator
How to Read a File at Compile Time
Advantage of Using Trailing Return Type in C++11 Functions
Immediate Exit of 'While' Loop in C++