Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 防止非类型模板参数中的类型冲突_C++_Templates_C++14 - Fatal编程技术网

C++ 防止非类型模板参数中的类型冲突

C++ 防止非类型模板参数中的类型冲突,c++,templates,c++14,C++,Templates,C++14,我通常使用std::size\t在模板参数中需要整数常量。但是我注意到,类型系统不能保护我不受那些乐于将负数作为参数传递给这些参数的用户的影响 例如,以下汇编产生了灾难性的结果: #include <iostream> template<std::size_t I> struct E1 { static void apply() { std::cout << I << std::endl; } };

我通常使用
std::size\t
在模板参数中需要整数常量。但是我注意到,类型系统不能保护我不受那些乐于将负数作为参数传递给这些参数的用户的影响

例如,以下汇编产生了灾难性的结果:

#include <iostream>

template<std::size_t I>
struct E1
{
     static void apply()
     {
         std::cout << I << std::endl;
     }
};

template<typename T>
constexpr T a = T { -1 }; 

template<std::size_t... Is>
void E2()
{
    for (auto&& i : {Is...}) std::cout << i << " "; 
    std::cout << std::endl;
}

int main()
{
    E1<-1>::apply();
    E2<-1, -2, -3>(); 
    //std::cout << a<std::size_t>; 
}
#包括
模板
结构E1
{
静态无效应用()
{

std::coutMy clang拒绝编译此文件:

test.cpp|24 col 8| error: non-type template argument evaluates to -1, which cannot be narrowed to type 'std::size_t' (aka 'unsigned long') [-Wc++11-narrowing]
 E1<-1>::apply();
    ^
test.cpp|25 col 5| error: no matching function for call to 'E2'
 E2<-1, -2, -3>(); 
 ^~~~~~~~~~~~~~
test.cpp|16 col 6| note: candidate template ignored: invalid explicitly-specified argument for template parameter 'Is'
 void E2()
test.cpp | 24 col 8 |错误:非类型模板参数的计算结果为-1,不能缩小为类型“std::size_t”(也称为“unsigned long”)[-Wc++11缩小]
E1::apply();
^
test.cpp | 25列5 |错误:调用“E2”时没有匹配函数
E2();
^~~~~~~~~~~~~~
test.cpp | 16 col 6 |注意:已忽略候选模板:为模板参数“Is”显式指定的参数无效
无效E2()
因此,在c++11中,它应该已经被禁止了


除此之外,这不是问题,因为模板参数实际上不会为负。可能会添加一个静态断言,表明该值在特定范围内。

这实际上是一个GCC错误,因为这里应该有一个用于缩小范围的诊断(警告或错误)。错误报告为,它有以下示例:

template<        char> void   f () {}
template<unsigned int> void   g () {}


template<unsigned int> struct A {};

int main () {

  f<1024> (); // ill-formed, `char { 1024 }` is a narrowing conversion,
              // see [dcl.init.list]p7

  g<-123> (); // ill-formed, `unsigned int { -123 }` is a narrowing
              // conversion, see [dcl.init.list]p7   

  A<-123>  a; // ill-formed, see previous comment
}

作为一个工作,你可以使用<代码> -WSCORE转换- Werror < /C> >()来警告这个情况并将其变成一个错误()。我原本认为这会被<代码> -WTIFE> 所捕获,但是 WSCOUNT转换< /COD>在C++中被默认关闭。

通常,您可以启用额外的警告。(
-Wimplicit
我认为它是GCC的一部分)
error: non-type template argument evaluates to -1, which cannot be narrowed to type 'std::size_t' (aka 'unsigned long') [-Wc++11-narrowing]
E1<-1>::apply();
   ^

error: no matching function for call to 'E2'
E2<-1, -2, -3>(); 
^~~~~~~~~~~~~~