旧OpenSiv3D(0.4.2)を 新バージョンVisualStudio2019(16.6.3)でビルドするとエラーが出る。
メリット
直せば、他の0.4.2のプロジェクト、すべて直ります。ライブラリ( OpenSiv 0.4.2 )本体のファイルを書き換えますので。
直し方
新規でopenSiv3D(0.4.2)プロジェクトを立ち上げ、ビルドするとエラーが出る。
該当の命令を右クリックして定義先へ飛ぶと InfiniteList.hpp
が表示される。
書き直す前に、バックアップをとっておき、内容を下記のものに書き直す。全部コピーして全部張り付ければOK。
もし何かあったら、バックアップしたInfiniteList.hpp から元通りにすれば大丈夫
InfiniteList.hpp
//-----------------------------------------------
//
// This file is part of the Siv3D Engine.
//
// Copyright (c) 2008-2019 Ryo Suzuki
// Copyright (c) 2016-2019 OpenSiv3D Project
//
// Licensed under the MIT License.
//
// OpenSiv 0.4.2A version C++20? C++17? エラー対処対応
//-----------------------------------------------
# pragma once
# include <type_traits>
# include "Fwd.hpp"
# include "Array.hpp"
# include "Step.hpp"
// C++20 check std::result_of_t(C++17) ==>> std::invoke_result_t(C++20)
#if _MSC_VER >= 1926
#define STD_INVOKE_RESULT_ARG std::invoke_result <Fty(value_type)>
#define STD_INVOKE_RESULT_T_ARG std::invoke_result_t <Fty(value_type)>
#else
#define STD_INVOKE_RESULT_ARG std::result_of <Fty(value_type)>;
#define STD_INVOKE_RESULT_T_ARG std::result_of_t <Fty(value_type)>
#endif
namespace s3d
{
template <class Type>
class InfiniteList
{
private:
Type m_startValue;
Type m_step;
public:
class Iterator
{
private:
Type m_currentValue;
Type m_step;
template <class IntegerType>
void checkOverflow() const
{
if constexpr (!IsBigInt_v<IntegerType>)
{
bool overflow = false;
if (m_step > 0)
{
if (m_currentValue > std::numeric_limits<Type>::max() - m_step)
{
overflow = true;
}
}
else if (m_step < 0)
{
if (m_currentValue < std::numeric_limits<Type>::min() - m_step)
{
overflow = true;
}
}
if (overflow)
{
throw std::overflow_error("infinite_iterator: integer overflow");
}
}
}
public:
Iterator()
: m_currentValue(Type())
, m_step(Type()) {}
Iterator(Type startValue, Type step)
: m_currentValue(startValue)
, m_step(step) {}
Iterator& operator ++()
{
checkOverflow<Type>();
m_currentValue += m_step;
return *this;
}
Iterator operator ++(int)
{
checkOverflow<Type>();
Iterator tmp = *this;
m_currentValue += m_step;
return tmp;
}
const Type& operator *() const { return m_currentValue; }
const Type* operator ->() const { return &m_currentValue; }
constexpr bool operator ==(const Iterator&) const { return false; }
constexpr bool operator !=(const Iterator&) const { return true; }
Type currentValue() const { return m_currentValue; }
Type step() const { return m_step; }
};
using value_type = Type;
using iterator = Iterator;
InfiniteList(Type startValue = 0, Type step = 1)
: m_startValue(startValue)
, m_step(step) {}
iterator begin() const { return iterator(m_startValue, m_step); }
iterator end() const { return iterator(); }
value_type startValue() const { return m_startValue; }
value_type step() const { return m_step; }
template <class Fty>
auto filter(Fty f) const;
template <class Fty>
auto map(Fty f) const;
Array<value_type> take(size_t n) const
{
Array<value_type> new_array;
for (auto it = begin(); n--; ++it)
{
new_array.push_back(*it);
}
return new_array;
}
template <class Fty>
Array<value_type> take_while(Fty f) const
{
Array<value_type> new_array;
for (auto it = begin(); f(*it); ++it)
{
new_array.push_back(*it);
}
return new_array;
}
};
namespace detail
{
template <class StepClass, class ValueType, class Tuple>
class F_InfStep
{
private:
StepClass m_base;
Tuple m_functions;
public:
using value_type = ValueType;
F_InfStep(StepClass stepClass, Tuple functions)
: m_base(stepClass)
, m_functions(functions) {}
template <class Fty>
auto filter(Fty f) const
{
const auto functions = std::tuple_cat(m_functions, std::make_tuple(FilterFunction<Fty>{ f }));
return F_InfStep<StepClass, value_type, decltype(functions)>(m_base, functions);
}
template <class Fty>
auto map(Fty f) const
{
using Ret = STD_INVOKE_RESULT_ARG;
const auto functions = std::tuple_cat(m_functions, std::make_tuple(MapFunction<Fty>{ f }));
return F_InfStep<StepClass, Ret, decltype(functions)>(m_base, functions);
}
Array<value_type> take(size_t n) const
{
Array<value_type> new_array;
if (n == 0)
{
return new_array;
}
auto it = m_base.begin();
const auto pushFunc = [&new_array](const auto& value) { new_array.push_back(value); };
const auto functions = m_functions;
for (;;)
{
Apply(pushFunc, *it, functions);
if (new_array.size() < n)
{
++it;
}
else
{
break;
}
}
return new_array;
}
template <class Fty>
Array<value_type> take_while(Fty f) const
{
Array<value_type> new_array;
bool finished = false;
auto it = m_base.begin();
const auto pushFunc = [&new_array, &finished, f = f](const auto& value)
{
if (f(value))
{
new_array.push_back(value);
}
else
{
finished = true;
}
};
const auto functions = m_functions;
for (;;)
{
Apply(pushFunc, *it, functions);
if (!finished)
{
++it;
}
else
{
break;
}
}
return new_array;
}
};
}
template <class Type>
template <class Fty>
inline auto InfiniteList<Type>::filter(Fty f) const
{
const auto tuple = std::make_tuple(detail::FilterFunction<Fty>{ f });
return detail::F_InfStep<InfiniteList, value_type, decltype(tuple)>(*this, tuple);
}
template <class Type>
template <class Fty>
inline auto InfiniteList<Type>::map(Fty f) const
{
using Ret = STD_INVOKE_RESULT_T_ARG; //C++20 std::result_of_t >> std::invoke_result_t
const auto tuple = std::make_tuple(detail::MapFunction<Fty>{ f });
return detail::F_InfStep<InfiniteList, Ret, decltype(tuple)>(*this, tuple);
}
}
その他、古い Visual Studio 2019 でも変更支障なし
上記ソースでは古いVisual Studio 2019では、Visual Studio 2019(16.6.3)以上の時だけ変更するように
プリプロセッサ(#if _MSC_VER >= 1926)で分岐させているので、
Visual Studio 2019(16.6.3) を入れていなくても上記を使用しても大丈夫です。
参考サイト
_MSC_VER の参考にしました。ページのずっと下の方に書かれています。
https://docs.microsoft.com/ja-jp/cpp/preprocessor/predefined-macros?view=vs-2019