Это продолжение Когда виден член класса?
После компиляции класса с помощью GCC, перемещая объявление pk_
в начало, я попытался использоватьэто:
#include <string>
#include <map>
#include <type_traits>
using from_type = std::map<std::string, std::string>;
template<typename PK, size_t N>
struct pf {
public:
PK pk_;
pf(from_type const& a, std::string const& pkn) noexcept(noexcept(fill(pk_, std::string{})))
: map_(a) // GCC 4.8 requires ()s for references
, pk_{ [&]{ fill(pk_, pkn); return pk_; }() }
{
}
template<typename prop_t>
typename std::enable_if<
std::is_integral<typename std::decay<prop_t>::type>::value,
pf<PK, N>>::type const&
fill(prop_t& , std::string const& , prop_t = 0) const noexcept(false);
pf<PK, N> const&
fill(std::string& , std::string const&) const noexcept;
protected:
from_type const& map_;
uint32_t aieee;
};
std::string k;
from_type m;
int i;
std::string s;
static_assert(!noexcept(pf<int , 42>{m, k}), "int could throw");
static_assert( noexcept(pf<std::string, 17>{m, k}), "string shouldn't throw");
clang 4.0, 6.0 и trunk снова скомпилировали программу.
GCC все еще не был доволен:
$ g++-99 -Wall -pedantic -Wextra -Wformat=2 -std=c++14 pf.cpp
pf.cpp: In instantiation of ‘pf<PK, N>::pf(const from_type&, const string&) [with PK = int; long unsigned int N = 42; from_type = std::map<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >; std::string = std::__cxx11::basic_string<char>]’:
pf.cpp:38:49: required from here
pf.cpp:12:74: error: no matching function for call to ‘fill(int&, std::__cxx11::basic_string<char>)’
12 | pf(from_type const& a, std::string const& pkn) noexcept(noexcept(fill(pk_, std::string{})))
| ~~~~^~~~~~~~~~~~~~~~~~~~
In file included from /usr/local/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/c++/bits/char_traits.h:39,
from /usr/local/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/c++/string:40,
from pf.cpp:1:
/usr/local/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/c++/bits/stl_algobase.h:742:5: note: candidate: ‘template<class _ForwardIterator, class _Tp> void std::fill(_ForwardIterator, _ForwardIterator, const _Tp&)’
742 | fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value)
| ^~~~
/usr/local/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/c++/bits/stl_algobase.h:742:5: note: template argument deduction/substitution failed:
pf.cpp:12:74: note: deduced conflicting types for parameter ‘_ForwardIterator’ (‘int’ and ‘std::__cxx11::basic_string<char>’)
12 | pf(from_type const& a, std::string const& pkn) noexcept(noexcept(fill(pk_, std::string{})))
| ~~~~^~~~~~~~~~~~~~~~~~~~
pf.cpp: In instantiation of ‘pf<PK, N>::pf(const from_type&, const string&) [with PK = std::__cxx11::basic_string<char>; long unsigned int N = 17; from_type = std::map<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >; std::string = std::__cxx11::basic_string<char>]’:
pf.cpp:39:49: required from here
pf.cpp:12:74: error: no matching function for call to ‘fill(std::__cxx11::basic_string<char>&, std::__cxx11::basic_string<char>)’
In file included from /usr/local/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/c++/bits/char_traits.h:39,
from /usr/local/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/c++/string:40,
from pf.cpp:1:
/usr/local/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/c++/bits/stl_algobase.h:742:5: note: candidate: ‘template<class _ForwardIterator, class _Tp> void std::fill(_ForwardIterator, _ForwardIterator, const _Tp&)’
742 | fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value)
| ^~~~
/usr/local/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/c++/bits/stl_algobase.h:742:5: note: template argument deduction/substitution failed:
pf.cpp:12:74: note: candidate expects 3 arguments, 2 provided
12 | pf(from_type const& a, std::string const& pkn) noexcept(noexcept(fill(pk_, std::string{})))
| ~~~~^~~~~~~~~~~~~~~~~~~~
pf.cpp:39:16: error: static assertion failed: string shouldn't throw
39 | static_assert( noexcept(pf<std::string, 17>{m, k}), "string shouldn't throw");
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Это сбивало с толку (кто-то сказал что-нибудьпро итераторы?) пока не увидел ответ на свой первый вопрос.Компилятор не мог видеть члены fill
, поэтому он попробовал единственный доступный ему метод fill
: метод из <algorithm>
, который был случайно включен через
. /usr/local/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/c++/string
.. /usr/local/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/c++/bits/char_traits.h
... /usr/local/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/c++/bits/stl_algobase.h
Так что я переименовалfill
членов для fillz
(включая оператор в noexcept
), что привело к:
$ g++-99 -Wall -pedantic -Wextra -Wformat=2 -std=c++14 pf.cpp
pf.cpp: In instantiation of ‘pf<PK, N>::pf(const from_type&, const string&) [with PK = int; long unsigned int N = 42; from_type = std::map<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >; std::string = std::__cxx11::basic_string<char>]’:
pf.cpp:38:49: required from here
pf.cpp:12:75: error: ‘fillz’ was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]
12 | pf(from_type const& a, std::string const& pkn) noexcept(noexcept(fillz(pk_, std::string{})))
| ~~~~~^~~~~~~~~~~~~~~~~~~~
pf.cpp:12:75: note: declarations in dependent base ‘pf<int, 42>’ are not found by unqualified lookup
pf.cpp:12:75: note: use ‘pf::fillz’ instead
pf.cpp:12:75: error: cannot call member function ‘const typename std::enable_if<std::is_integral<typename std::decay<prop_t>::type>::value, pf<PK, N> >::type& pf<PK, N>::fillz(prop_t&, const string&, prop_t) const [with prop_t = int; PK = int; long unsigned int N = 42; typename std::enable_if<std::is_integral<typename std::decay<prop_t>::type>::value, pf<PK, N> >::type = pf<int, 42>; std::string = std::__cxx11::basic_string<char>]’ without object
pf.cpp: In instantiation of ‘pf<PK, N>::pf(const from_type&, const string&) [with PK = std::__cxx11::basic_string<char>; long unsigned int N = 17; from_type = std::map<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >; std::string = std::__cxx11::basic_string<char>]’:
pf.cpp:39:49: required from here
pf.cpp:12:75: error: ‘fillz’ was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]
pf.cpp:12:75: note: declarations in dependent base ‘pf<std::__cxx11::basic_string<char>, 17>’ are not found by unqualified lookup
pf.cpp:12:75: note: use ‘pf::fillz’ instead
pf.cpp:12:75: error: cannot call member function ‘const pf<PK, N>& pf<PK, N>::fillz(std::string&, const string&) const [with PK = std::__cxx11::basic_string<char>; long unsigned int N = 17; std::string = std::__cxx11::basic_string<char>]’ without object
pf.cpp:39:16: error: static assertion failed: string shouldn't throw
39 | static_assert( noexcept(pf<std::string, 17>{m, k}), "string shouldn't throw");
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Очевидно, что GCC все еще не может видеть участника (теперь называется fillz
), нопочему он жалуется на зависимые основания?Struct pf
не имеет ничего общего с наследованием.Может ли это быть из-за того, что проблема видимости чаще всего возникает с зависимыми базами?
В конце концов, правильное использование оказалось:
noexcept(noexcept(std::declval<pf&>().fill(std::declval<PK&>(), std::string{})))