简体   繁体   English

C ++可变参数模板,递归decltype

[英]C++ variadic template, recursion decltype

I know there are already a lot of questions concerning this topic, but so far I found no response that satisfactorily answers the following questions. 我知道有关此主题的问题已经很多,但是到目前为止,我没有找到令人满意的回答以下问题的答案。 Given the following code. 给出以下代码。

#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;
}

A call to 致电

map<int, int, int>() 

shall return an object 将返回一个对象

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

and this works perfectly for up to three template parameters. 并且非常适合多达三个模板参数。 As mentioned in the code calling the pair function with four template parameters fails and g++ (5.1.0) returns the following error. 如代码中所述,使用四个模板参数调用对函数会失败,并且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()
                                   ^

Therefore my questions are: 因此,我的问题是:

  • Is this issue g++ related? 这个问题与g ++有关吗?
  • What is the designated way to solve this problem? 解决此问题的指定方法是什么?

Manipulating types with types is usually easier. 用类型操纵类型通常更容易。

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...>>;
};

does what you want. 做你想要的。

If you really want it as a function: 如果您确实希望将其用作功能:

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

does the trick. 绝招。

A function is not in context during its own declaration, so your map overload cannot see itself as a valid candidate for map in its own return type. 一个函数在其自己的声明期间不在上下文中,因此,您的map重载不能以其自己的返回类型将自身视为map的有效候选者。

You can get around this via ADL (both the context of its own declaration, and the ADL at point of function invocation, are considered to find overloads), but it isn't needed. 您可以通过ADL来解决这个问题(它本身的声明的上下文和函数调用时的ADL都被认为可以找到重载),但这不是必需的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM