随着C ++ 14中的变量模板(以及Clang已经支持它们)和标准is_same_v
的提议以及同样类型的特征,我认为能够制作新的类型特征如下: / p>
template<typename T>
constexpr bool is_const_and_volatile{std::is_const_v<T> && std::is_volatile_v<T>};
唉,这导致错误等同于以下SSCCE(this one包含下面提到的所有内容):
#include <type_traits>
template<typename T>
constexpr bool is_pointer{std::is_pointer<T>::value};
template<typename T>
constexpr bool foo{is_pointer<T>};
int main() {
//foo<int *>;
}
在main
评论中,Clang吐出以下内容:
警告:变量
is_pointer<type-parameter-0-0>
具有内部链接但未定义
它看起来对我有用(请注意,在T
中将int *
更改为foo
可以正常工作。取消注释main
中的行以实例化foo
可以解决此问题(再次,T
到int *
可以正常工作):
错误:constexpr变量
初始化foo<int *>
必须由常量表达式
但是,使用以下旧语法替换foo
会导致两个实例都正常工作:
constexpr bool foo{std::is_pointer<T>::value};
关于变量模板,我有什么遗漏吗?有没有办法用构建新的变量模板,或者我是否被迫使用旧语法来构建新的模板,并且在将它们用于其他代码时只享受语法糖?
答案 0 :(得分:3)
您的代码有效,并且已被clang SVN接受。链接错误是由clang bug 17846引起的,我fixed a couple of days ago。
答案 1 :(得分:0)
以下似乎有效:
#include <type_traits>
#include <iostream>
template<typename T>
struct test {
static constexpr bool is_pointer{std::is_pointer<T>::value};
};
template<typename T>
constexpr bool test<T>::is_pointer;
template<typename T>
constexpr bool foo{test<T>::is_pointer};
int main() {
std::cout << foo<bool>;
std::cout << foo<bool*>;
}
虽然如果在constexpr
上下文中使用它会触发相同的警告,所以我认为它毕竟不起作用。
// Fail
template<typename T>
typename std::enable_if<foo<T>, void>::type bar()
{
}
int main() {
bar<bool*>();
}
main.cpp:21:5: error: no matching function for call to 'bar'
bar<bool*>();
^~~~~~~~~~
main.cpp:16:45: note: candidate template ignored: substitution failure [with T = bool *]: non-type template argument is not a constant expression
typename std::enable_if<foo<T>, void>::type bar()
如果你给foo
一个明确的类型,它会停止抱怨:
template<typename T>
typename std::enable_if<foo<bool*>, void>::type bar()
{
}
或者直接使用test<T>::is_pointer
:
template<typename T>
typename std::enable_if<test<T>::is_pointer, void>::type bar()
{
}