【发布时间】:2014-04-25 02:14:50
【问题描述】:
以下示例 (ideone) 在 Windows 7 上使用 Visual Studio 2013 时编译并运行,但在 Ubuntu 13.10 上使用 g++4.8.1 时编译并运行。
#include <cassert>
#include <cstdlib>
#include <array>
#include <iostream>
#include <numeric>
#include <utility>
// Wraps a std::array of TKey/TValue pairs and provides a method
// to randomly select a TKey with TValue bias.
template< typename TKey, typename TValue, std::size_t TSize >
class weights final
{
public:
using pair = const std::pair< const TKey, const TValue >;
using array = const std::array< pair, TSize >;
weights( array values )
: values_{ values }
, sum_{ std::accumulate(values_.begin(), values_.end(), 0, [](TValue total, const pair& p){ return total + p.second; }) }
{}
// Implements this algorithm
// http://stackoverflow.com/a/1761646/331024
const TKey get() const
{
// The real code uses c++11 <random> features,
// which I've removed for brevity.
auto weight_rand = static_cast< TValue >( std::rand() % sum_ );
for ( std::size_t i = 0; i < TSize; ++i )
{
if (weight_rand < values_[i].second)
{
return values_[i].first;
}
weight_rand -= values_[i].second;
}
assert(false);
}
private:
array values_;
const TValue sum_;
};
enum class direction
{
NORTH,
SOUTH,
EAST,
WEST
};
// For convenience create a type to map the above
// four-value enumeration to integer weights.
using w4i = weights< direction, int, 4 >;
// Map the directions with a weight.
static const w4i direction_weights = w4i::array{
{
w4i::pair{ direction::NORTH, 2 },
w4i::pair{ direction::EAST, 1 },
w4i::pair{ direction::SOUTH, 3 },
w4i::pair{ direction::WEST, 1 }
}
};
int main()
{
std::cout << (int)direction_weights.get() << std::endl;
return 0;
}
Visual Studio 2013 可以编译和运行代码。 g++-4.8.1编译失败,输出如下错误:
$ g++ -std=c++11 -Wall -Wextra -pedantic weights.cpp -o weights
weights.cpp: In instantiation of ‘weights<TKey, TValue, TSize>::weights(array) [with TKey = direction; TValue = int; long unsigned int TSize = 4ul; weights<TKey, TValue, TSize>::array = const std::array<const std::pair<const direction, const int>, 4ul>]’:
weights.cpp:67:5: required from here
weights.cpp:20:131: error: could not convert ‘values’ from ‘weights<direction, int, 4ul>::array {aka const std::array<const std::pair<const direction, const int>, 4ul>}’ to ‘const std::pair<const direction, const int>’, sum_{ std::accumulate(values_.begin(), values_.end(), 0, [](TValue total, const pair& p){ return total + p.second; }) }
如何修复/修改它以与两个编译器一起使用?
【问题讨论】:
-
Fwiw,它也会在 clang 3.4 上呕吐(相同/类似的错误)。将
values_成员类型更改为const array,或者在using arraydecl 中丢失const,两者之一。 -
@WhozCraig 感谢您的铿锵反馈。我现在所拥有的与您建议的更改之间的功能差异是什么?
-
这是一些花哨的 const 正确性……还有几个额外的
const以防万一…… -
@DavidRodríguez-dribeas
const应该是所有内容的默认值! :) 看着那段代码,我可以看到一些错过的const机会,这让我很紧张!我对@WhozCraig 的问题是合法的:using array = const ...不意味着数组成员变量也是const? -
g++ 4.7.2 在权重构造函数中给出
array must be initialized with a brace-enclosed initializer。 (sum {...线)
标签: c++ visual-studio c++11 g++ visual-studio-2013