标签: variable-templates

C++ 14警告:变量的模板头太多(应为0)

在尝试使用最近的g ++ - 5编译器时,我在一个文件中写下了以下语句:

template<T> T a;
template<> int a = 1;
Run Code Online (Sandbox Code Playgroud)

结果如下:

警告:模板标题太多a(应为0)

同样有效的是,它并不专门a<int>.例如

template<typename T> T a;
template<> int a = 1;

int main ()  {
  std::cout << a<double> << "\n";  // prints 0; OK
  std::cout << a<int> << "\n";  // prints 0! why not 1?
}
Run Code Online (Sandbox Code Playgroud)

这句法的神秘之处是什么?

c++ template-specialization language-lawyer variable-templates c++14

19
推荐指数
1
解决办法
1011
查看次数

模板类中的变量模板 - 意外错误(可能是错误?)

有:

struct Value
{
    template<class T>
    static constexpr T value{0};
};
Run Code Online (Sandbox Code Playgroud)

(0) 意思号

template<typename TValue>
struct Something
{
    void x()
    {
        static_assert(TValue::template value<int> == 0, "");
    }
};

int main() { Something<Value>{}.x(); return 0; } 
Run Code Online (Sandbox Code Playgroud)
  • 不用clang ++ 3.6编译.

    错误:如果没有模板参数列表,则无法引用变量模板'value'

  • 不使用g ++ 5.2编译.

    错误:'template constexpr const T Value :: value'不是函数模板


(1) 理想

用clang ++和g ++编译.

struct Something
{
    void x()
    {
        static_assert(Value::template value<int> == 0, "");
    }
};

int main() { Something{}.x(); return 0; } 
Run Code Online (Sandbox Code Playgroud)

为什么(0)无法编译?

如果通过模板参数(在本例中)访问变量模板,似乎会出现问题 …

c++ templates auto variable-templates c++14

19
推荐指数
1
解决办法
799
查看次数

在Class范围内声明时,如何在C++ 14中引用变量模板?

例如:

class example{
    public:
        template <class T> static constexpr T var = T(1.5);
};

int main(){

    int a = example::var<int>;

    example obj;
    int b = obj.var<int>;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

GCC会产生以下错误: 'example::var<T>' is not a function template'var' is not a member template function

Clang正确编译第一个但是第二个产生错误: cannot refer to member 'var' in 'example' with '.'

根据C++ 14标准(ISO/IEC 14882:2014):

第14节,第1段.

类作用域中的变量模板是静态数据成员模板.

第9.4节,第2段.

可以使用qualified-id表达式X :: s来引用类X的静态成员; 没有必要使用类成员访问语法(5.2.5)来引用静态成员.可以使用类成员访问语法来引用静态成员,在这种情况下,评估对象表达式.

因此,可以以两种方式引用恕我直言,类范围的变量模板(即,静态数据成员模板).它可能是编译器中的错误吗?

我发现试图证明这种行为的唯一理由是第9.4.2节第1段中的这句话:

静态数据成员不是类的子对象的一部分.

但是,上述两个段落仍然有效.此外,我尝试了同样的例子,引用其他静态成员,如变量,函数和函数模板,并且所有这些成员都在GCC和Clang中成功编译.

class example{
    public:
        static int constexpr variable = 1;
        void static function(){ …
Run Code Online (Sandbox Code Playgroud)

c++ templates static-members variable-templates c++14

17
推荐指数
1
解决办法
628
查看次数

使用变量模板的递归计算 - gcc vs clang

考虑以下示例:

#include <cstdio>

template <int N>
int fib = fib<N - 1> + fib<N - 2>;

template <> int fib<2> = 1;
template <> int fib<1> = 1;

int main()
{
    std::printf("%d %d %d", fib<4>, fib<5>, fib<6>);
}
Run Code Online (Sandbox Code Playgroud)
  • GCC 7.x、8.x、9.x 和 10.x 都打印出3 5 8.

  • 结果是 Clang 5.x、6.x、7.x、8.x、9.x 和 10.x 都打印出来1 3 4了。

Godbolt.org 上的现场示例


Clang的行为令人惊讶。

我缺少的 C++ 标准中的变量模板实例化、全局变量和递归之间是否存在任何微妙的交互?

或者这是一个长期存在的 Clang 错误?

顺便说一下,标记fibconstexpr解决了这个问题(在 Godbolt.org 上)。

c++ recursion language-lawyer variable-templates c++14

14
推荐指数
1
解决办法
228
查看次数

是否需要初始化参考变量主模板,即使它从未实例化过?

在没有初始化主要参考模板的情况下在C++ 14中声明参考模板是否合法,只要它从未实例化?

template<class T>
const T& ref;

template<>
auto ref<int> = 1;

auto x = ref<int>;
Run Code Online (Sandbox Code Playgroud)

这会在GCC和Clang上产生不同的结果:

$ g++ -std=c++14 -c ref.cpp
$

$ clang -std=c++14 -c ref.cpp
ref.cpp:2:10: error: declaration of reference variable 'ref' requires an
      initializer
const T& ref;
         ^~~
1 error generated.
Run Code Online (Sandbox Code Playgroud)

没有必要初始化主要参考模板,因为在实例化之前,它是模板,而不是参考.

我发现我可以这样做:

template<class T>
const T& ref = "Meaningless initialization with any value of any type";

template<>
auto ref<int> = 1;

auto x = ref<int>;
Run Code Online (Sandbox Code Playgroud)

因为显然GCC和Clang都接受但忽略了参考模板初始化器RHS,只要它是一个有效的表达式并且主参考模板永远不会被实例化.任何类型的任何表达式都满足Clang的初始化要求.

只要主参考模板从未实例化,GCC就不需要初始化程序.这似乎是"在精神上"的正确行为,因为在实际实例化参考模板之前,它不应该需要初始化器.

标准在参考模板上不是100%明确.这是我在变量模板实例化上找不到的东西:

14.7.1

除非已显式实例化或显式专门化变量模板特化,否则在使用特化时隐式实例化变量模板特化.

...

实现不应隐式实例化......不需要实例化的变量模板.

14.7.2

除了内联函数,从其初始值或返回值(7.1.6.4)推导出的类型的声明const …

c++ templates language-lawyer clang++ variable-templates

12
推荐指数
1
解决办法
214
查看次数

可以将变量模板作为模板模板参数传递吗?

以下荒谬的示例无法编译,但是还有其他方法可以将变量模板作为模板模板参数传递吗?

template<typename T>
constexpr auto zero = T{0};

template<typename T, template<typename> auto VariableTemplate>
constexpr auto add_one()
{
    return VariableTemplate<T> + T{1};
}

int main()
{
    return add_one<int, zero>();
}
Run Code Online (Sandbox Code Playgroud)

尝试编译器资源管理器

c++ templates template-templates variable-templates c++14

11
推荐指数
1
解决办法
108
查看次数

转发声明constexpr变量模板

我试图constexpr像这样向前声明一个变量模板:

template<typename>
constexpr std::size_t iterator_category_value;
Run Code Online (Sandbox Code Playgroud)

我们的目标是记录每一项专业都应该是,constexpr但我必须承认,我从未检查过它是否合法,而且g ++对它很满意.但是,当我尝试使用clang ++编译此spinnet时,我收到以下错误:

error: default initialization of an object of const type 'const std::size_t' (aka 'const unsigned long')
    constexpr std::size_t iterator_category_value;
                          ^
                                                  = 0
Run Code Online (Sandbox Code Playgroud)

错误是有道理的,删除constexpr使它消失,所以这不是一个真正的问题.但是,我现在很好奇:标准是否允许constexpr对变量模板进行此类前向声明,还是非法?g ++和clang ++似乎不同意,我想知道如果需要我应该在哪里提交错误报告.

他们都抱怨一个前向声明的constepxr变量,它不是一个变量模板,所以变量模板上下文似乎是编译器不同意的原因.

c++ language-lawyer constexpr variable-templates c++14

10
推荐指数
2
解决办法
722
查看次数

变量模板模板?

假设您有一个元组类型,并且您想要提取其模板参数包以便实例化另一个模板.如果那是一个类型模板,那么我可以有这样的实用程序:

template < typename Tuple, template <typename...> typename What >
struct PutTupleInT;

template < typename... Types, template <typename...> typename What >
struct PutTupleInT<std::tuple<Types...>, What>
{
    using Result = What<Types...>;
};
Run Code Online (Sandbox Code Playgroud)

但是,如果所需模板是可变模板呢?虽然template <typename...> typename What是类型模板的"占位符",但是变量模板的"占位符"是什么?

我已经尝试了以下forng-4.0.0(现在唯一支持自动类型的非类型模板参数的编译器),但它失败了.实际上我不确定这是否是C++ 17的正确语法.

template < typename Tuple, template <typename...> auto What >
struct PutTupleInV;

template < typename... Types, template <typename...> auto What >
struct PutTupleInV<std::tuple<Types...>, What>
{
    static constexpr auto value = What<Types...>;
};
Run Code Online (Sandbox Code Playgroud)

c++ template-templates variable-templates c++14 c++17

9
推荐指数
1
解决办法
307
查看次数

在Visual Studio中使用Lambdas进行模板化变量错误?

提供了可变模板,它在,但在lambdas中它们似乎分崩离析.例如:

template <typename T>
const auto PI = std::acos(static_cast<T>(-1));

int main() {
  auto func = []() { cout << PI<float> << endl; };

  func();
}
Run Code Online (Sandbox Code Playgroud)

在gcc 6.3上输出:

3.14159

在Visual Studio 2017上,此输出:

0.0

c++ lambda variable-templates c++14 visual-studio-2017

9
推荐指数
1
解决办法
297
查看次数

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

随着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>};
Run Code Online (Sandbox Code Playgroud)

唉,这会导致错误等同于以下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 *>;
}
Run Code Online (Sandbox Code Playgroud)

main评论中,Clang吐出以下内容:

警告:变量is_pointer<type-parameter-0-0>具有内部链接但未定义

它看起来定义为我的(注意,更改Tint *foo正常工作).在取消注释行main实例foo给出了这样的(再次,Tint *优良工程):

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

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

constexpr bool foo{std::is_pointer<T>::value};
Run Code Online (Sandbox Code Playgroud)

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

c++ variable-templates c++14

8
推荐指数
1
解决办法
398
查看次数