我想编写这段代码,但它会产生错误。
template<int N>
struct A {
struct B {
};
B f() { return B{}; }
};
template<typename T>
constexpr bool val = false;
template<int N>
constexpr bool val<typename A<N>::B> = true;
error: template parameters not deducible in partial specialization:
13 | constexpr bool val<typename A<N>::B> = true;
虽然这段代码运行完美
template<int N> struct A;
template<int N>
struct AB {
};
template<int N>
struct A {
AB<N> f() { return AB<N>{}; }
};
template<typename T>
constexpr bool val = false;
template<int N>
constexpr bool val<AB<N>> = true;
我理解C++在评估
N
时必须检查是否存在T
使得A<N>::B
等于val<T>
,这太困难了。这就是为什么会出现错误。但我的问题是:有没有办法将结构体 B 保留在 A 中并为每个 val<A<N>::B>
定义值 N
?
我理解如果 B 被定义为对 A 外部结构的引用(例如
using B = int;
)的错误,但如果 B 是 A 内部定义的结构,则不会有歧义,并且 N
很容易推断出来。
最简单的解决方案是在类外部定义它,并在类中使用类型别名来正常使用它:
template<int N> struct A;
template<int N>
struct AB {
friend A<N>;
};
template<int N>
struct A {
using B = AB<N>;
friend B;
B f() { return B{}; }
};
template<typename T>
constexpr bool val = false;
template<int N>
constexpr bool val<AB<N>> = true;
这和嵌套
struct B
之间几乎没有什么区别。
您可以使用老式类型的特征,将测试分为两部分。
A<N>
。A<N>
是否定义类 B
。template<class T>
struct is_A_with_B {
static std::false_type test(...);
template<class U> // test that the A<N> has a class B
static auto test2(U&&) -> class U::B;
template<int N> // if it's actually an A<N>, check test2 above
static constexpr auto test(A<N>&&) -> decltype(test2(std::declval<A<N>>()),
std::true_type{});
static constexpr bool value = decltype(test(std::declval<T>()))::value;
};
template<typename T>
constexpr bool val = is_A_with_B<T>::value;