<commit_before>/*
 * Copyright 2013 <NAME>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef LIBQ_PROMISE_DEFER_HPP
#define LIBQ_PROMISE_DEFER_HPP

namespace q {

namespace detail {

template< typename... T >
class defer
: public std::enable_shared_from_this< defer< T... > >
{
public:
	typedef ::q::arguments< T... >                          arguments_type;
	typedef std::tuple< T... >                              tuple_type;
	typedef expect< tuple_type >                            expect_type;
	typedef detail::promise_state_data< tuple_type, false > state_data_type;
	typedef detail::promise_state< tuple_type, false >      state_type;
	typedef promise< tuple_type >                           promise_type;
	typedef shared_promise< tuple_type >                    shared_promise_type;

	void set_expect( expect_type&& exp )
	{
		if ( exp.has_exception( ) )
			set_exception( exp.exception( ) );
		else
			set_value( exp.consume( ) );
	}

	/**
	 * Sets the expected value based on an expect< tuple< expect< > > >
	 */
	void set_inner_expect( ::q::expect< std::tuple< > >&& exp )
	{
		if ( exp.has_exception( ) )
		{
			set_value(
				::q::refuse< void >( exp.exception( ) ) );
		}
		else
		{
			set_value( ::q::fulfill< void >( ) );
		}
	}

	/**
	 * Sets the expected value based on an expect< tuple< expect< _T > > >
	 */
	template< typename _T >
	typename std::enable_if<
		sizeof...( T ) == 1
		and
		::q::is_argument_same_or_convertible<
			::q::arguments< _T >,
			arguments_type
		>::value
	>::type
	set_inner_expect( ::q::expect< std::tuple< _T > >&& exp )
	{
		if ( exp.has_exception( ) )
		{
			set_value( ::q::refuse< _T >( exp.exception( ) ) );
		}
		else
		{
			auto tuple = exp.consume( );
			auto inner_value = std::move( std::get< 0 >( tuple ) );
			set_value( ::q::fulfill< _T >(
				std::move( inner_value ) ) );
		}
	}

	inline void set_value( tuple_type&& tuple )
	{
		auto value = ::q::fulfill< tuple_type >( std::move( tuple ) );
		promise_.set_value( std::move( value ) );
		signal_->done( );
	}

	inline void set_value( const tuple_type& tuple )
	{
		auto value = ::q::fulfill< tuple_type >( tuple );
		promise_.set_value( std::move( value ) );
		signal_->done( );
	}
<commit_msg>Reference compile issue in defer::set_value<commit_after>/*
 * Copyright 2013 <NAME>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef LIBQ_PROMISE_DEFER_HPP
#define LIBQ_PROMISE_DEFER_HPP

namespace q {

namespace detail {

template< typename... T >
class defer
: public std::enable_shared_from_this< defer< T... > >
{
public:
	typedef ::q::arguments< T... >                          arguments_type;
	typedef std::tuple< T... >                              tuple_type;
	typedef expect< tuple_type >                            expect_type;
	typedef detail::promise_state_data< tuple_type, false > state_data_type;
	typedef detail::promise_state< tuple_type, false >      state_type;
	typedef promise< tuple_type >                           promise_type;
	typedef shared_promise< tuple_type >                    shared_promise_type;

	void set_expect( expect_type&& exp )
	{
		if ( exp.has_exception( ) )
			set_exception( exp.exception( ) );
		else
			set_value( exp.consume( ) );
	}

	/**
	 * Sets the expected value based on an expect< tuple< expect< > > >
	 */
	void set_inner_expect( ::q::expect< std::tuple< > >&& exp )
	{
		if ( exp.has_exception( ) )
		{
			set_value(
				::q::refuse< void >( exp.exception( ) ) );
		}
		else
		{
			set_value( ::q::fulfill< void >( ) );
		}
	}

	/**
	 * Sets the expected value based on an expect< tuple< expect< _T > > >
	 */
	template< typename _T >
	typename std::enable_if<
		sizeof...( T ) == 1
		and
		::q::is_argument_same_or_convertible<
			::q::arguments< _T >,
			arguments_type
		>::value
	>::type
	set_inner_expect( ::q::expect< std::tuple< _T > >&& exp )
	{
		if ( exp.has_exception( ) )
		{
			set_value( ::q::refuse< _T >( exp.exception( ) ) );
		}
		else
		{
			auto tuple = exp.consume( );
			auto inner_value = std::move( std::get< 0 >( tuple ) );
			set_value( ::q::fulfill< _T >(
				std::move( inner_value ) ) );
		}
	}

	inline void set_value( tuple_type&& tuple )
	{
		auto value = ::q::fulfill< tuple_type >( std::move( tuple ) );
		promise_.set_value( std::move( value ) );
		signal_->done( );
	}

	inline void set_value( const tuple_type& tuple )
	{
		auto value = ::q::fulfill< tuple_type >( tuple_type( tuple ) );
		promise_.set_value( std::move( value ) );
		signal_->done( );
	}

{'fraction_non_alphanumeric': 0.1336489439184268, 'fraction_numerical': 0.003641660597232338, 'mean_word_length': 2.9833212472806383, 'pattern_counts': {'":': 0, '<': 67, '<?xml version=': 0, '>': 71, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '801083', 'n_tokens_mistral': 1977, 'n_tokens_neox': 1795, 'n_words': 501}