c++ - Overloaded templated function declaration order -
c++ - Overloaded templated function declaration order -
i have code reads sscce:
#include <map> #include <string> #include <functional> using std::map; using std::string; using std::function; using std::forward; template<typename totype, typename... fromtypes> totype construct(fromtypes&&... fromtypes) { homecoming totype(forward<fromtypes>(fromtypes)...); } class variant { public: map<string, variant> tomap() const; }; map<string, variant> variant::tomap() const { homecoming { {"test", {}}, {"test1", {}}, }; } // #1 template <typename maptype> maptype varianttomap(variant const& v) { // expect error on next line because it's referencing function labeled #4 has not been declared yet. homecoming varianttomap<maptype>(v, construct<typename maptype::key_type, string>, construct<typename maptype::mapped_type, variant>); } // #2 template <typename maptype> maptype varianttomap(variant const& v, function<typename maptype::key_type(string)> const& keyconvert) { // expect error on next line because it's referencing function labeled #4 has not been declared yet. homecoming varianttomap<maptype>(v, keyconvert, construct<typename maptype::mapped_type, variant>); } // #3 template <typename maptype> maptype varianttomap(variant const& v, function<typename maptype::mapped_type(variant)> const& valueconvert) { // expect error on next line because it's referencing function labeled #4 has not been declared yet. homecoming varianttomap<maptype>(v, construct<typename maptype::key_type, string>, valueconvert); } // #4 template <typename maptype> maptype varianttomap(variant const& v, function<typename maptype::key_type(string)> const& keyconvert, function<typename maptype::mapped_type(variant)> const& valueconvert) { maptype res; (auto pair : v.tomap()) { res[keyconvert(pair.first)] = valueconvert(pair.second); } homecoming res; } int main() { variant a; // #1 varianttomap<map<string, variant>>(a); // #2 { int counter = 0; varianttomap<map<int, variant>>(a, [&counter](string) -> int { homecoming ++counter; }); } // #3 varianttomap<map<string, int>>(a, [](variant) -> int { homecoming 42; }); // #4 { int counter = 0; varianttomap<map<int, int>>(a, [&counter](string) -> int { homecoming ++counter; }, [](variant) -> int { homecoming 42; }); } homecoming 0; }
which compiles , works fine.
however, because it's declared out of order, expected have thrown errors. assume reason why it's not related fact these functions templated. however, still bit confusing me because (for instance) phone call varianttomap #4 within varianttomap #1 has 3 arguments, means
is clang , gcc inappropriately accepting these functions, or allowed? , if allowed, what's rationale it?
it should noted have reordered these functions, i'm curious why worked in first place.
c++ uses two phase name lookup resolve identifiers found in template definitions. (unless have msvc, uses sec phase only).
when template declared/defined, names not depend on template arguments resolved. when instantiated, names depend on template arguments resolved. time, names visible @ point of instantiation participate , can found during lookup.
in case inner varianttomap
calls depend on template arguments, not resolved until outer functions called. @ point 4 variants visible , can found.
c++ templates language-lawyer
Comments
Post a Comment