我可以使用变量模板来声明另一个变量模板吗?

时间:2014-01-26 02:12:56

标签: c++ c++14 variable-templates

随着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可以解决此问题(再次,Tint *可以正常工作):

  

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

初始化

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

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

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

2 个答案:

答案 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*>;
}

Live Example

虽然如果在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()
{
}