I was curious if this is defined behavior in C++23 to have a template-template that takes a typename, and be able to insert a template which accepts a concept (which accepts a typename)?
Here is an example:
#include <iostream>
#include <type_traits>
template<typename T>
concept MyConcept = std::is_integral_v<T> || std::is_floating_point_v<T>;
template<template<typename> typename TT>
struct A {
template<typename T>
using Type = TT<T>;
};
template<MyConcept T>
struct B {
T bb;
};
int main(int argc, char** args)
{
auto a = A<B>{}; // Ok? Compiles with gcc 13.2.1 and clang-16.0.6
auto b = decltype(a)::Type<int>{};
return 0;
}
The converse also seems to compile which makes me more suspicious
template<template<MyConcept> typename TT>
struct A {
template<typename T>
using Type = TT<T>;
};
template<typename T>
struct B {
T bb;
};
int main(int argc, char** args)
{
auto a = A<B>{}; // Ok? Compiles with gcc 13.2.1 and clang-16.0.6
auto b = decltype(a)::Type<int>{};
return 0;
}
Here, under a certain reading, we should accept a template into the template-template iff that template accepts a MyConcept, but B's template is unconstrained?
Are either of these examples undefined behavior, or are they behaving as the standard defines?
Thank you!
According to the publicly available working draft of the C++23 standard it seems like this is defined behavior and is correct. Example 4 under § 13.4.4 paragraph 3 seems to show exactly this, from the standard:
Also this from example 2 looked relevant: