<html>
<head>
<base href="https://bugs.llvm.org/">
</head>
<body><table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Bug ID</th>
<td><a class="bz_bug_link
bz_status_NEW "
title="NEW - static constexpr member variable template requires fully qualified name"
href="https://bugs.llvm.org/show_bug.cgi?id=43394">43394</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>static constexpr member variable template requires fully qualified name
</td>
</tr>
<tr>
<th>Product</th>
<td>clang
</td>
</tr>
<tr>
<th>Version</th>
<td>unspecified
</td>
</tr>
<tr>
<th>Hardware</th>
<td>All
</td>
</tr>
<tr>
<th>OS</th>
<td>All
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Severity</th>
<td>normal
</td>
</tr>
<tr>
<th>Priority</th>
<td>P
</td>
</tr>
<tr>
<th>Component</th>
<td>C++17
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedclangbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>coachhagins@gmail.com
</td>
</tr>
<tr>
<th>CC</th>
<td>blitzrakete@gmail.com, erik.pilkington@gmail.com, llvm-bugs@lists.llvm.org, richard-llvm@metafoo.co.uk
</td>
</tr></table>
<p>
<div>
<pre>In some cases, a static variable template must be fully qualified, otherwise a
compiler error is generated.
The same behavior occurs in all versions from 6.00 up to and including the
trunk (though the more recent versions have slightly different error messages).
Compile the following code with -std=c++17 -DSHOWISSUE to see the errors.
Exclude -DSHOWISSUE to get a clean compilation.
#include <type_traits>
#include <utility>
#include <cstdint>
template <typename T>
struct remove_cvref : std::remove_cv<std::remove_reference_t<T>> { };
template <typename T>
using remove_cvref_t = typename remove_cvref<T>::type;
template <typename T>
class Foo final
{
template <typename U>
static constexpr bool isThis = std::is_same_v<Foo, remove_cvref_t<U>>;
#if SHOWISSUE
template <typename U>
using WhenThis = std::enable_if_t<isThis<U>, bool>;
#else
template <typename U>
using WhenThis = std::enable_if_t<Foo::isThis<U>, bool>;
#endif
public:
using ValueType = T;
constexpr Foo() = default;
template <typename V,
std::enable_if_t<not isThis<V>
&& std::is_constructible_v<ValueType, V>, bool> = true>
constexpr explicit Foo(V && v)
noexcept(noexcept(ValueType(std::forward<V>(v))))
: value_(std::forward<V>(v))
{
}
constexpr ValueType const & value() const { return value_; }
private:
T value_;
template <typename U, WhenThis<U> = true>
friend constexpr auto operator+=(U & self, U const & that)
-> decltype(self.value_ += that.value(), self)
{
self.value_ += that.value();
return self;
}
};
template <typename T>
constexpr auto operator+(Foo<T> const &x, Foo<T> const &y)
-> decltype(std::declval<Foo<T> &>() += y, Foo<T>(x))
{
auto result = x;
result += y;
return result;
}
template <typename T1, typename T2,
std::enable_if_t<not std::is_same_v<Foo<T1>, Foo<T2>>, bool> = true,
typename CT = Foo<std::common_type_t<T1, T2>>>
auto
constexpr operator+(const Foo<T1> & x, const Foo<T2> & y)
-> decltype(CT(x.value()) + CT(y.value()))
{
return CT(x.value()) + CT(y.value());
}
template <typename T, typename U>
constexpr auto check(Foo<T> x, Foo<U> y)
{
return x + y;
}
static_assert(42 == check(Foo<int>(41), Foo<int>(1)).value());
static_assert(42 == check(Foo<int>(41), Foo<long>(1)).value());</pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are on the CC list for the bug.</li>
</ul>
</body>
</html>