C++11 从c++;11标准还是我发现了一些编译器错误?

C++11 从c++;11标准还是我发现了一些编译器错误?,c++11,g++,constexpr,clang++,C++11,G++,Constexpr,Clang++,我正在使用constexpr关键字并编写以下简单程序: #include <iostream> using namespace std; template<typename T> constexpr bool is_equal(T const* array1, T const* array2, size_t len) { return array1 == array2 || (len ? array1[len - 1] == array2[len - 1] &

我正在使用constexpr关键字并编写以下简单程序:

#include <iostream>

using namespace std;

template<typename T>
constexpr bool is_equal(T const* array1, T const* array2, size_t len)
{
    return array1 == array2 || (len ? array1[len - 1] == array2[len - 1] && is_equal<T>(array1, array2, len - 1) : true);
}

template<typename T, size_t N1, size_t N2>
constexpr bool is_equal(T const (&array1)[N1], T const (&array2)[N2])
{
    return N1 == N2 && is_equal<T>(array1, array2, N1);
}



template<typename T, size_t N>
constexpr size_t arraylength(T const (&array)[N])
{
    return N;
}



constexpr size_t stringlength(char const* str, size_t len=0)
{
    return str ? (*str ? stringlength(str + 1, len + 1) : len) : 0;
}



constexpr size_t min(size_t one, size_t another)
{
    return one < another ? one : another;
}



constexpr size_t min_length(char const* str1, char const* str2)
{
    return min(stringlength(str1), stringlength(str2));
}



template<typename T, size_t N1, size_t N2>
constexpr size_t min_length(T const (&array1)[N1], T const (&array2)[N2])
{
    return min(N1, N2);
}



template<bool cond=false>
struct to_num
{
    enum {value=0};
};

template<>
struct to_num<true>
{
    enum {value=42};
};



template<size_t init>
struct two_times
{
    enum {value=init*2};
};



static constexpr char x[]{"One string"};
static constexpr char y[]{"One string"};

static constexpr int a[]{1,2,3,4};
static constexpr int b[]{1,2,3,4};

static constexpr int const* const c = &a[0];
static constexpr int const* const d = &b[0];

int main()
{
    cout << "The two literals are equal: " << to_num< is_equal("One string", "One string") >::value << endl; // COMPILES AND WORKS IN GCC BUT NOT IN CLANG
    cout << "The two variables x & y are equal: " << to_num< is_equal(x, y) >::value << endl;
    cout << "Pointers a & c are equal: " << to_num< a == c >::value << endl;
    cout << "Pointers b & c are equal: " << to_num< b == c >::value << endl;
    cout << "Pointers c & d are equal: " << to_num< c == d >::value << endl;
    cout << "The contents of c & d is the same: " << to_num< is_equal(c, d, arraylength(a)) >::value << endl;
    cout << "Pointers a & b are equal: " << to_num< a == b >::value << endl;
    cout << "The contents of a & b is the same: " << to_num< is_equal(a, b) >::value << endl;
    cout << "String x contains " << two_times< stringlength(x) >::value / 2 << " characters" << endl; // COMPILES AND WORKS IN CLANG BUT NOT IN GCC
    cout << "String literal contains " << two_times< stringlength("literal") >::value / 2 << " characters" << endl; // COMPILES AND WORKS IN CLANG BUT NOT IN GCC
    cout << "Array literal contains " << two_times< arraylength("literal") >::value / 2 << " values" << endl;
    return 0;
}
那么,我是在用这段代码做c++11标准之外的事情,还是这两个编译器都有问题

请注意,如果我删除了g++有问题的行,但保留了clang++有问题的行,那么代码将编译并使用g++工作;如果我删除了clang++有问题的行,保留了g++有问题的行,那么代码将编译并使用clang正常工作++

还要注意,我使用两个模板结构强制编译器在编译时解析函数


感谢您的时间和经验。

更新:

  • GCC阻塞了您的函数
    stringlength
    。试试这个:

    constexpr size_t stringlength(char const* str, size_t i=0)
    {
        return str ? (str[i] ? 1 + stringlength(str, i+1) : 0) : 0;
    }
    
  • 根据GCC 4.6.3,这似乎是可疑的:

    static constexpr int const* c = &a[0];
    static constexpr int const* d = &b[0];
    
    试试这个:

    constexpr size_t stringlength(char const* str, size_t i=0)
    {
        return str ? (str[i] ? 1 + stringlength(str, i+1) : 0) : 0;
    }
    
    static constexpr int* c = &a[0];
    static constexpr int* d = &b[0];
    
  • 旧答案:

    您的代码似乎是正确的,使用GCC4.6.3它也可以编译

    int main()
    {
        const char* a = "hallo";
        const char* b = "qallo";
        std::cout << is_equal(a,b,5) << std::endl;
        constexpr const char* c = "hallo";
        std::cout << is_equal(a,c,5) << std::endl;
    }
    
    intmain()
    {
    const char*a=“你好”;
    const char*b=“qallo”;
    
    std::cout您所说的
    arraylelength
    示例不适用于GCC,它适用于GCC 4.7和4.8,除了关于
    constepr const
    的一个无关错误外,也适用于GCC 4.6

    至于您的
    stringlength
    示例:这是GCC的一个限制。我知道我已经看到了关于它的错误报告。您可以通过重写
    stringlength
    函数来解决它:

    constexpr size_t stringlength(char const* str, size_t len=0)
    {
      return str ? (str[len] ? stringlength(str, len + 1) : len) : 0;
    }
    

    但据我所知,你已经得到的是完全有效的。

    你能试着把你的例子缩小一点吗?这不像是重模板的
    C++11
    代码从一开始就是一种阅读的乐趣。
    T\uu
    不是你的程序可以使用的名称。鉴于此,编译器所做的一切都是有效的。(但不管是GCC还是clangcare)@mic_e这是“高度模板化的
    C++11
    ”?我想知道你在工作时会怎么称呼我的代码。comiler?我想要它。在任何地方带有双下划线的标识符都是保留的。原始形式的
    stringlength
    函数是完全正确的。你的解决方法也是正确的,避免了GCC的错误。我和g++4.8.2
    -Wall-Wextra-pedantic
    不明白为什么2.应该是可疑的.4.6.3不喜欢它…我想说
    constexpr
    意味着
    const
    静态
    在这里也不应该是必需的。hvd和您都向我指出gnu编译器的正确工作区。我让troube选择谁应该标记正确的答案,但在阅读评论时,似乎Danvil的答案排在第一位。Y你对arraylength函数在我的原始代码中正确工作的看法是正确的。编辑我的答案。
    int main()
    {
        const char* a = "hallo";
        const char* b = "qallo";
        std::cout << is_equal(a,b,5) << std::endl;
        constexpr const char* c = "hallo";
        std::cout << is_equal(a,c,5) << std::endl;
    }
    
    constexpr size_t stringlength(char const* str, size_t len=0)
    {
      return str ? (str[len] ? stringlength(str, len + 1) : len) : 0;
    }