C++变量模板,递归decltype

C++ variadic template, recursion decltype

本文关键字:递归 decltype 变量 C++      更新时间:2023-10-16

我知道关于这个话题已经有很多问题了,但到目前为止,我还没有找到满意地回答以下问题的答案。给定以下代码。

#include <map>
template<typename T, typename K>
std::map<T, K> map()
{
    return std::map<T, K>();
}
template<typename T, typename...K>
std::map<T, decltype(map<K...>())> map()
{
    return std::map<T, decltype(map<K...>())>();
}

int main(int argc, char **argv)
{
    std::map<int, int> m2 = map<int, int>();
    std::map<int, std::map<int, int>> m3 = map<int, int, int>();    
    std::map<int, std::map<int, std::map<int, int>>> m4 = map<int, int, int, int>();    // <- Compile Error here
    return 0;
}

呼叫

map<int, int, int>() 

应返回一个对象

std::map<int, std::map<int, int>>

并且这对于多达三个模板参数来说是完美的。如代码中所述,使用四个模板参数调用pair函数失败,g++(5.1.0)返回以下错误。

main.cpp: In function 'int main(int, char**)':
main.cpp:20:84: error: no matching function for call to 'map()'
      std::map<int, std::map<int, std::map<int, int>>> m4 = map<int, int, int, int>(); // <- Compile Error here
                                                                                    ^
main.cpp:4:20: note: candidate: template<class T, class K> std::map<T, K> map()
     std::map<T, K> map()
                    ^
main.cpp:4:20: note:   template argument deduction/substitution failed:
main.cpp:20:84: error: wrong number of template arguments (4, should be 2)
      std::map<int, std::map<int, std::map<int, int>>> m4 = map<int, int, int, int>(); // <- Compile Error here
                                                                                    ^
main.cpp:10:40: note: candidate: template<class T, class ... K> std::map<T, decltype (map<K ...>())> map()
     std::map<T, decltype(map<K...>())> map()
                                        ^
main.cpp:10:40: note:   template argument deduction/substitution failed:
main.cpp: In substitution of 'template<class T, class ... K> std::map<T, decltype (map<K ...>())> map() [with T = int; K = {int, int, int}]':
main.cpp:20:84:   required from here
main.cpp:10:35: error: no matching function for call to 'map()'
     std::map<T, decltype(map<K...>())> map()
                                   ^
main.cpp:4:20: note: candidate: template<class T, class K> std::map<T, K> map()
     std::map<T, K> map()
                    ^
main.cpp:4:20: note:   template argument deduction/substitution failed:
main.cpp:10:35: error: wrong number of template arguments (3, should be 2)
     std::map<T, decltype(map<K...>())> map()
                                   ^

因此,我的问题是:

  • 这个问题与g++有关吗
  • 解决这个问题的指定方法是什么

用类型操作类型通常更容易。

template<class K0, class K1, class...Ks>
struct my_map;
template<class K0, class K1, class...Ks>
using my_map_t = typename my_map<K0,K1,Ks...>::type;

template<class K0, class K1>
struct my_map<K0,K1>{using type=std::map<K0, K1>;};
template<class K0, class K1, class K2, class...Ks>
struct my_map<K0, K1, K2, Ks...>{
  using type=std::map<K0, my_map_t<K1, K2, Ks...>>;
};

做你想做的事。

如果你真的想把它作为一个功能:

template<class K0, class K1, class...Ks>
my_map_t<K0, K1, Ks...> map() { return {}; }

真的很管用。

函数在其自身声明期间不在上下文中,因此map重载在其自身的返回类型中不能将其自身视为map的有效候选者。

您可以通过ADL绕过这一点(它自己声明的上下文和函数调用时的ADL都被认为是查找重载),但这不是必需的。