8

随着 C++14 中的变量模板(并且 Clang 已经支持它们)以及标准is_same_v和类似类型特征的提议,我认为能够按如下方式制作新的类型特征会很整洁:

template<typename T>
constexpr bool is_const_and_volatile{std::is_const_v<T> && std::is_volatile_v<T>};

唉,这会导致相当于以下 SSCCE 的错误(这个包含下面提到的所有内容):

#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>具有内部链接但未定义

它看起来对我来说是定义的(请注意,更改Tint *infoo可以正常工作)。取消注释main以实例化的行foo给出了这个(再次,T工作int *正常):

错误:constexpr 变量foo<int *>必须由常量表达式初始化

但是,替换foo为以下旧语法会导致两个实例都可以正常工作:

constexpr bool foo{std::is_pointer<T>::value};

关于变量模板,我有什么遗漏吗?有没有办法它们构建新的变量模板,或者我是否被迫使用旧语法来构建新的,并且只在将它们用于其他代码时才享受语法糖?

4

2 回答 2

3

您的代码是有效的,并且被 clang SVN 接受。链接错误是由我几天前修复的clang 错误 17846引起的。

于 2014-02-05T20:28:03.393 回答
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()
{
}
于 2014-01-26T04:43:25.377 回答