C++ 使用decltype获取表达式';s类型,不带常量

C++ 使用decltype获取表达式';s类型,不带常量,c++,c++11,decltype,C++,C++11,Decltype,考虑以下计划: int main () { const int e = 10; for (decltype(e) i{0}; i < e; ++i) { // do something } } int main() { 常数int=10; for(decltype(e)i{0};i

考虑以下计划:

int main ()
{
    const int e = 10;

    for (decltype(e) i{0}; i < e; ++i) {
        // do something
    }
}
int main()
{
常数int=10;
for(decltype(e)i{0};i
无法使用clang(以及gcc)进行编译:

decltype.cpp:5:35:错误:只读变量不可赋值
for(decltype(e)i{0};i
基本上,编译器假定
i
必须是常量,因为
e
是常量

是否有一种方法可以使用
decltype
来获取
e
的类型,但删除
const
说明符?

使用:

#包括
...
对于(std::remove_const::type i{0};i
我更喜欢
auto I=decltype(e){0};
这样做。它比使用
type\u traits
要简单一些,而且我觉得它更明确地指定了您希望将变量初始化为
e
类型的0的意图


我最近用了很多,所以我可能有偏见。

我更喜欢范围。模拟非常简单

#include <iostream>

template< typename T >
struct range_t
{
    struct iter
    {
        T operator * ()const noexcept { return n;}
        iter& operator ++()noexcept{ ++n; return *this;}
        friend
        bool operator != (iter const& lhs, iter const& rhs)noexcept
        { return lhs.n != rhs.n;}

        T n;
    };

    iter begin()const noexcept {return {b};}
    iter end() const noexcept{ return {e};}
    T b, e;
};
template< typename T > range_t<T>  range(T b, T e){ return {b,e}; }

int main()
{
    const int e = 10;

    for( auto i : range(0,e) )
    {
        std::cout << i << ' ';
    }
    return 0;
}
#包括
模板
结构范围
{
结构iter
{
T运算符*()常量noexcept{return n;}
iter&运算符++()无异常{++n;返回*this;}
朋友
bool运算符!=(国际热核实验堆常数和lhs、国际热核实验堆常数和rhs)无例外
{返回lhs.n!=rhs.n;}
T n;
};
iter begin()常量noexcept{return{b};}
iter end()常量noexcept{return{e};}
tb,e;
};
模板range\u T range(tb,te){return{b,e};}
int main()
{
常数int=10;
用于(自动i:范围(0,e))
{
std::cout您还可以使用:

#包括
...
对于(std::decation::type i{};i
尚未提及的解决方案:

for (decltype(+e) i{0}; i < e; ++i)
for(decltype(+e)i{0};i

原语类型的Prvalues具有
const
剥离;因此
+e
int
类型的prvalue,因此
decltype(+e)
int

std::remove_const\t i{0}
有了C++14,知道这一点太好了。谢谢你的提示。@KerrekSB auto在这里也不起作用。它会给我一个
int
,无论
e
是否是
int
for(auto end=e,i=0;i!=end;++i)
..@KerrekSB如果
e
不是
int
@KerrekSB,那么我得到的是对“auto”不一致的推断,因为在“逗号分隔的自动声明”中推断出的所有类型都必须是相同的。@ChristianRau:
auto end=e,I{}
?这很好。它用简洁的语法回答了我想要的真正问题。这会额外调用
delctype(e)
?还是C++11修复了这种情况?
decltype(e){}
会更一般。我不喜欢这种方法,因为这种方法是针对这样一个简单的应用程序的锅炉板代码。现在,它可以在其他环境中使用。我看不到编译器为此创建的代码与普通for循环的代码一样高效。@greendiod您只需声明一次样板文件。@LucBloom启用了优化,g++为基于范围的for和普通for输出相同的程序集:应该是
typename std::decay::type
。C++14添加了一个别名来缩短它,
std::decay\u t
这将强制类型为
int
,而不是从泛型类型中删除
常量。不过,还是很酷的把戏!@CameronTacklind我猜你指的是I正在应用的nteger升级--比
int
小的类型升级为
int
,但其他类型不变。如果
e
long
,则
i
long
(非
int
)。
#include <iostream>

template< typename T >
struct range_t
{
    struct iter
    {
        T operator * ()const noexcept { return n;}
        iter& operator ++()noexcept{ ++n; return *this;}
        friend
        bool operator != (iter const& lhs, iter const& rhs)noexcept
        { return lhs.n != rhs.n;}

        T n;
    };

    iter begin()const noexcept {return {b};}
    iter end() const noexcept{ return {e};}
    T b, e;
};
template< typename T > range_t<T>  range(T b, T e){ return {b,e}; }

int main()
{
    const int e = 10;

    for( auto i : range(0,e) )
    {
        std::cout << i << ' ';
    }
    return 0;
}
#include<type_traits>
...
for (std::decay<decltype(e)>::type i{}; i < e; ++i) {
  // do something
}
for (decltype(+e) i{0}; i < e; ++i)