负数组索引和看似冗余的模板用法

时间:2016-10-18 13:22:40

标签: c++ templates boost compiler-errors

我遇到了以下几行代码:

template< int I > struct arg
{
    arg()
    {
    }

    template< class T > arg( T const & /* t */ )
    {
        // static assert I == is_placeholder<T>::value
        typedef char T_must_be_placeholder[ I == is_placeholder<T>::value? 1: -1 ];
    }
};

template< class T > struct is_placeholder
{
    enum _vt { value = 0 };
};

结构is_placeholder被模板化的原因是什么,而typename T未在内部任何地方使用?

为什么T_must_be_placeholder以这样的方式定义,以便它可以具有无效的大小-1。为了实现这一点,我致电arg<1>(1)并按预期给出了error: size of array is negative。是某种理智检查技术吗?如果没有进行arg<1>(1)调用,为什么编译器不会报告此问题?

虽然

int i = 0;
char a[i == 1 ? 1 : -1]; //No error

如果第一个例子的健全性检查有效,那么第二个例子如何失败?

1 个答案:

答案 0 :(得分:0)

is_placeholder是一个模板,因此可以专门用于不同的T。假设我创建一个结构example并希望is_placeholder<example>::value为42.我会这样做:

struct example {};

template< class T > struct is_placeholder
{
    enum _vt { value = 0 };
};

template<>
struct is_placeholder<example>
{
    enum _vt { value = 42 };
};

template< int I > struct arg
{
    arg()
    {
    }

    template< class T > arg( T const & /* t */ )
    {
        // static assert I == is_placeholder<T>::value
        typedef char T_must_be_placeholder[ I == is_placeholder<T>::value ? 1: -1 ];
    }
};

void test()
{
    auto x = arg<42>(example()); // compiles
    auto y = arg<43>(example()); // assertion
    return 0;
}

在这种情况下,T_must_be_placeholder会检查is_placeholder<example>::value(我们专门为42)与I是否相同。因此,如果I为42,则会编译,但如果I为其他内容,则不会。

尝试创建一个负数大小的数组是故意阻止代码编译的一种方式,所以是的,这可能是一个完整性检查(静态断言,正如它在评论中所说)。