C++ std::transform 副作用

标签 c++ stl

我已经实现了这样的 UnaryOperation

struct Converter
{
    Converter( std::size_t value ):
        value_( value ), i_( 0 )
    {}
    std::string operator() ( const std::string& word )
    {
        return ( value_ & ( 1 << i_++ ) ) ?
            word:
            std::string( word.size(), ' ' );
    }
    std::size_t value_;
    std::size_t i_;
};

我喜欢用它

std::vector v;
// initialization of v  
std::transform( v.begin(), v.end(),
                std::back_inserter( result ),
                Converter( data ) );

我的问题是我能否依赖我的假设,即算法将按照“Converter::i_”将对应于“v”中的元素数量的顺序调用我的“Converter operator ()” .

请引用标准,以防我不能依赖订单或放置类似 STL 的解决方案,以避免可能出现的问题。

谢谢。

编辑:

我知道转换算法标准中的“无副作用”要求。我无法在同一标准中找到仿函数的确切“副作用”。

也许这个任务有一些看起来不错的类似 boost 的解决方案?

最佳答案

来自标准:

25.2.3 Transform [lib.alg.transform]
Requires:
op and binary_op shall not have any side effects.

Side Effect ( wikipedia definition )

在你的情况下我们有下一个副作用:

Converter c( data );  
c( some_const_value ) != c( some_const_value );

你对你的算法没有任何保证,但我相信它适用于几乎所有的 STL 实现。

建议的解决方案
看来我知道一种方法来满足您的需求:
使用 boost::counting_iterator - 迭代两个容器;

它看起来像:

bool bit_enabled( size_t data, unsigned char number )
{
    return ( data & 1 << number ) != 0;
}

std::string select_word( 
                const std::string& word,
                size_t data, 
                size_t number )
{
    return bit_enabled( data, number ) ? word : std::string( ' ', word.length() );
}

const size_t data = 7;
const boost::array< std::string, 3 > vocabulary = { "a", "b", "c" };
std::vector< std::string > result;
std::transform(
    vocabulary.begin(),
    vocabulary.end(),
    boost::counting_iterator< size_t >(0),
    back_inserter( result ),
    boost::bind( &select_word, _1, data, _2 )
);

此外,如果您将定义位迭代器或将使用一些位容器,您可以使用 boost::zip_iterator 来迭代这两个容器。

编辑:
昨天我找到了interest article其中包含标准的副作用定义。

The Standard defines a side effect as follows: Accessing an object designated by a volatile lvalue, modifying an object, calling a library I/O function, or calling a function that does any of those operations are all side effects, which are changes in the state of the execution environment.

编辑:
我希望这是最新的编辑。
我一直认为“没有副作用”是什么意思:
f(a) 应该始终等于 f(a)。 ( f 独立于执行环境:内存/cpu/全局变量/成员变量,如您的情况等)。
“不产生副作用”的意思是——不改变执行环境。

但在 C++ 标准中,我们对副作用有更多的低级定义。

你在你的例子中所做的事情被命名为 Stateful 仿函数。
标准没有说明“有状态”仿函数,也没有说明仿函数的拷贝数 - 你不能使用这个技巧,因为它是未指定的行为。

参见标准库问题列表(与 predicat 类似的问题):
http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-active.html#92

关于C++ std::transform 副作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/708742/

相关文章:

c++ - OpenCV 不释放相机

c++ - std::set `erase ( const key_type& x )` 是否以与 ` erase ( collection.find( x ) );` 相同的方式在 STL 中实现?

c++ - 编译 gcc/g++/libstdc++ 时的 --enable-threads=LIB 是什么意思?

c++ - 在没有默认构造函数的情况下减小 std::vector 的大小

c++ - 是否可以在C++中的 union 中声明匿名实例?

c++ - 无法让基数排序算法在 C++ 中工作

c++ - constexpr 的运行时错误

c++ - 异步接受与 boost 绑定(bind)

c++ - STL 中不必要的锁定? (Visual C++ Express)

C++ 设置迭代器删除