零大小的数组不使用模板 [英] Zero-sized arrays don't work with templates

查看:166
本文介绍了零大小的数组不使用模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用GCC,似乎模板参数替换总是失败与零大小的数组。我期望 static_assert 失败,并在测试1 打印邮件,就像它与测试2 。结果
您也可以删除 static_assert S,模板不与零大小的数组工作。

由于零大小的阵列是一个延伸,当然有没有关于在C ++标准其中的特殊处理规则,所以我的问题是:结果
难道我错过了什么,这是一个错误,或者是这个由GCC作者意图?

 的#include<&iostream的GT;模板<为size_t的len>
TEST1无效(为const char(安培; ARR)[LEN])
{
    static_assert(LEN大于0,为什么我从来没有印?);
}模板<为size_t的len>
空TEST2(为const char(安培; ARR)[LEN])
{
    static_assert(LEN大于10,我将打印);
}诠释的main()
{
    炭arr5 [5];
    TEST2(arr5);    炭arr0 [0];
    TEST1(arr0);
}

错误输出:

  main.cpp中:在函数'廉政的main():
main.cpp中:21:15:错误:没有匹配函数调用'TEST1(的char [0])
     TEST1(arr0);
               ^
main.cpp中:21:15:注:候选人是:
main.cpp中:4:6:注意:模板和LT; unsigned int类型LEN> TEST1无效(为const char(&安培;)[LEN])
 TEST1无效(为const char(安培; ARR)[LEN])
      ^
main.cpp中:4:6:注意:模板参数推导/替换失败:
main.cpp中:在实例无效test2的(常量字符(安培)[长度])[与unsigned int类型的len = 5U]':
main.cpp中:18:15:从这里需要
main.cpp中:12:5:错误:无法静态断言:我将打印
     static_assert(LEN大于10,我将打印);
     ^

我的编译器的版本是:

  G ++(Ubuntu的4.8.4-2ubuntu1〜14.04)4.8.4


更新:我用Visual C ++ 2015年的今天测试了它,它显示了相同的行为。 VC ++支持,只有当他们是一类/结构的最后一个成员零大小的数组,但如果code为相应的改变,这是完全一样的相克++:

函数模板从来没有零大小的数组编译。为什么呢?

 的#include<&iostream的GT;结构s_arr
{
    炭arr0 [0];
};模板<为size_t的len>
无效测试(为const char(安培; ARR)[LEN])
{
}诠释的main()
{
    s_arr S;
    TEST1(s.arr0);
}


解决方案

  

难道我错过了什么,这是一个错误,或者是由GCC作者特意这样?


在模板接受零大小的数组将导致无论是一致性的问题或无法维护的语言。

由于

 模板< INT N'GT;无效F(CHAR(*)[N],INT);
模板< INT N'GT;无效F(void *的,无效*);

呼叫 F< 1>(0,0)必须的使用第一个重载,因为它是第二个参数更好的匹配。

呼叫 F&℃的GT(0,0)必须的使用第二个重载,因为SFINAE丢弃第一个重载由于零大小的数组。

零尺寸的阵列,只要它们不改变任何标准C ++程序的语义允许作为扩展。允许模板参数替换期间零大小的数组会改变一个标准的C ++程序的语义,除非例外的整个列表被实现,其中零大小的数组不应该被允许。

Using GCC, it seems template argument substitution always fails with a zero-sized array. I would expect the static_assert to fail and print the message in test1, just like it does with test2.
You can also remove the static_asserts, the template does not work with the zero-sized array.

Since zero-sized arrays are an extension, there surely is no rule about special treatment of them in the C++ standard, so my question is:
Do I miss something, is this a bug, or is this intended by the GCC authors?

#include <iostream>

template <size_t len>
void test1(const char(&arr)[len])
{
    static_assert(len > 0, "why am I never printed?");
}

template <size_t len>
void test2(const char(&arr)[len])
{
    static_assert(len > 10, "I will be printed");
}

int main()
{
    char arr5[5];
    test2(arr5);

    char arr0[0];
    test1(arr0);
}

Error output:

main.cpp: In function ‘int main()’:
main.cpp:21:15: error: no matching function for call to ‘test1(char [0])’
     test1(arr0);
               ^
main.cpp:21:15: note: candidate is:
main.cpp:4:6: note: template<unsigned int len> void test1(const char (&)[len])
 void test1(const char(&arr)[len])
      ^
main.cpp:4:6: note:   template argument deduction/substitution failed:
main.cpp: In instantiation of ‘void test2(const char (&)[len]) [with unsigned int len = 5u]’:
main.cpp:18:15:   required from here
main.cpp:12:5: error: static assertion failed: I will be printed
     static_assert(len > 10, "I will be printed");
     ^

My compiler version is:

g++ (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4


Update: I tested it with Visual C++ 2015 today, it shows the same behaviour. VC++ supports zero-sized arrays only if they are the last member of a class/struct, but if the code is changed accordingly, it's exactly the same as with g++:

The function template never compiles with zero-sized arrays. Why?

#include <iostream>

struct s_arr
{
    char arr0[0];
};

template <size_t len>
void test(const char(&arr)[len])
{
}

int main()
{
    s_arr s;
    test1(s.arr0);
}

解决方案

Do I miss something, is this a bug, or is this intended by the GCC authors?

Accepting zero-sized arrays in templates would lead to either conformance issues or an impossible-to-maintain language.

Given

template <int N> void f(char (*)[N], int);
template <int N> void f(void *, void *);

A call f<1>(0, 0) must use the first overload because it is a better match for the second argument.

A call f<0>(0, 0) must use the second overload because SFINAE discards the first overload due to the zero-sized array.

Zero-sized arrays are allowed as an extension so long as they do not alter the semantics of any standard C++ program. Allowing zero-sized arrays during template argument substitution would alter the semantics of a standard C++ program, unless a whole list of exceptions gets implemented where zero-sized arrays should not be allowed.

这篇关于零大小的数组不使用模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆