请考虑以下代码:
#include <type_traits>
template <typename T>
struct wrapper {
T& ref;
constexpr wrapper(T& ref) : ref(ref) {}
};
// Trait that checks whether a type is of the form `wrapper<T>`
template <typename T>
struct is_wrapper_type : std::false_type {};
template <typename T>
struct is_wrapper_type<wrapper<T>> : std::true_type {};
// Trait that checks whether an object is of the type `wrapper<T>`
template <auto& Value>
struct is_wrapper_object;
template <auto& Value>
requires (!is_wrapper_type<std::decay_t<decltype(Value)>>::value)
struct is_wrapper_object<Value> : std::false_type {};
template <auto& Value>
requires is_wrapper_type<std::decay_t<decltype(Value)>>::value
struct is_wrapper_object<Value> : std::true_type {};
int main() {
static constexpr int v = 42;
static_assert(!is_wrapper_object<v>::value);
static constexpr wrapper w {v};
static_assert(is_wrapper_object<w>::value);
}
字符串
上面的fails to compile in Clang with the errors shown below but compiles successfully in GCC。
<source>:30:20: error: implicit instantiation of undefined template 'is_wrapper_object<v>'
30 | static_assert(!is_wrapper_object<v>::value);
| ^
<source>:18:8: note: template is declared here
18 | struct is_wrapper_object;
| ^
<source>:32:19: error: implicit instantiation of undefined template 'is_wrapper_object<w>'
32 | static_assert(is_wrapper_object<w>::value);
| ^
<source>:18:8: note: template is declared here
18 | struct is_wrapper_object;
| ^
型
这里哪个编译器是正确的?
我相信GCC在这里应该是正确的,因为上面的代码 * 应该 * 在纸面上是法律的的,但是,我不确定是否真的是这样。
此外,如果我将特征is_wrapper_object
的定义改为:
template <auto& Value>
struct is_wrapper_object : std::false_type {};
template <auto& Value>
requires is_wrapper_type<std::decay_t<decltype(Value)>>::value
struct is_wrapper_object<Value> : std::true_type {};
1条答案
按热度按时间w1e3prcc1#
GCC是正确的。
请注意,只需将
const auto&
替换为const auto&
,代码就可以同时编译。无论问题是什么,它都与部分专门化中的占位符类型说明符有关。请注意:
如果模板参数的类型
T
包含placeholder type或推导类类型的占位符([dcl.type.class. defect]),则参数的类型是在本发明的声明中为变量x
推导的类型字符串
也就是说,模板参数中的
auto&
经过这样的推导后,应该是const int&
和const wrapper&
,而不需要用户自己提供const
。我找不到相关的LLVM bug报告,所以我提交了一个:LLVM Bug 77189。
最小可复制示例
参见https://godbolt.org/z/rhKsWKdPz
型
由此,我们可以看出clang * 完全 * 无法在
test
的部分特化中推导出Value
。