kakoune/src/ranges.cc
Johannes Altmanninger 8a7109f9c5 Fix compilation due to failing template deduction for aggregates
gcc 11.2.0 compiles us just fine but clang 13.0.1 fails with this error

	clang++ -DKAK_DEBUG -O0 -pedantic -std=c++2a -g -Wall -Wextra -Wno-unused-parameter -Wno-sign-compare -Wno-address -frelaxed-template-template-args -Wno-ambiguous-reversed-operator -MD -MP -MF .ranges.debug.d -c -o .ranges.debug.o ranges.cc
	ranges.cc:30:17: error: no viable constructor or deduction guide for deduction of template arguments of 'Array'
	    check_equal(Array{{""_sv, "abc"_sv, ""_sv, "def"_sv, ""_sv}} | flatten(), "abcdef"_sv);
	                ^
	./constexpr_utils.hh:14:8: note: candidate template ignored: couldn't infer template argument 'T'
	struct Array
	       ^
	./constexpr_utils.hh:14:8: note: candidate function template not viable: requires 0 arguments, but 1 was provided
	1 error generated.

The same error can be reproduced with this C++ input

	template<typename T, int N>
	struct Array
	{
	    T m_data[N];
	};
	void test() {
	    (void)Array{{1, 2}};
	}

Since "Array" has no constructor, the compiler uses aggregate
initialization. Only recent g++ seems to be smart enough to deduce
template arguments in this case. Help other compilers by adding a
deduction guide. The deduction guide needs to count the array elements
to infer the array size, hence we need to remove braces. Happily,
this is allowed and it's also what std::array does.

Closes #4597
2022-04-28 19:34:36 +02:00

36 lines
1.5 KiB
C++

#include "ranges.hh"
#include "unit_tests.hh"
#include "string.hh"
#include "string_utils.hh"
namespace Kakoune
{
UnitTest test_ranges{[] {
using Strs = ConstArrayView<StringView>;
auto check_equal = [](auto&& container, auto&& expected) {
kak_assert(std::equal(container.begin(), container.end(), expected.begin(), expected.end()));
};
check_equal("a,b,c"_sv | split<StringView>(','), Strs{"a", "b", "c"});
check_equal(",b,c"_sv | split<StringView>(','), Strs{"", "b", "c"});
check_equal(",b,"_sv | split<StringView>(','), Strs{"", "b", ""});
check_equal(","_sv | split<StringView>(','), Strs{"", ""});
check_equal(""_sv | split<StringView>(','), Strs{});
check_equal("a,b,c,"_sv | split_after<StringView>(','), Strs{"a,", "b,", "c,"});
check_equal("a,b,c"_sv | split_after<StringView>(','), Strs{"a,", "b,", "c"});
check_equal(R"(a\,,\,b,\,)"_sv | split<StringView>(',', '\\')
| transform(unescape<',', '\\'>), Strs{"a,", ",b", ","});
check_equal(R"(\,\,)"_sv | split<StringView>(',', '\\')
| transform(unescape<',', '\\'>), Strs{",,"});
check_equal(R"(\\,\\,)"_sv | split<StringView>(',', '\\')
| transform(unescape<',', '\\'>), Strs{R"(\)", R"(\)", ""});
check_equal(Array{""_sv, "abc"_sv, ""_sv, "def"_sv, ""_sv} | flatten(), "abcdef"_sv);
check_equal(Vector<StringView>{"", ""} | flatten(), ""_sv);
check_equal(Vector<StringView>{} | flatten(), ""_sv);
}};
}