如何解决模板参数推导中的const/non-const冲突

Wyz*_*a-- 5 c++ templates c++11 type-deduction c++14

我有一个函数模板,它取一个std::pair对的类型之一的值.我想使用a std::map作为pair参数的条目来调用此函数.

#include <map>
#include <utility>

template <typename T1, typename T2>
void do_stuff(std::pair<T1, T2> const &pair, T1 const &val) {
  // Imagine that this does something important...
}

int main() {
  std::map<int, float> foo { { 0, 0.0 } };

  do_stuff(*foo.begin(), 0);
}
Run Code Online (Sandbox Code Playgroud)

这无法编译,因为地图条目std::pair<const int, float>的类型是,因此类型推导T1具有冲突类型:const int通过pair参数,并int通过val参数.

test.cc: In function ‘int main()’:
test.cc:12:27: error: no matching function for call to ‘do_stuff(std::pair<const int, float>&, int)’
   do_stuff(*foo.begin(), 0);
                           ^
test.cc:5:6: note: candidate: template<class T1, class T2> void do_stuff(const std::pair<_T1, _T2>&, const T1&)
 void do_stuff(std::pair<T1, T2> const &pair, T1 const &val) {
      ^~~~~~~~
test.cc:5:6: note:   template argument deduction/substitution failed:
test.cc:12:27: note:   deduced conflicting types for parameter ‘const T1’ (‘const int’ and ‘int’)
   do_stuff(*foo.begin(), 0);
                           ^
Run Code Online (Sandbox Code Playgroud)

解决这场冲突的最佳方法是什么?理想情况下,我希望T1将其推断为int,但const int如果实现起来更为直接,则可以.

我发现我可以通过使用解决的错误std::remove_conststd::decay对类型val参数:

void do_stuff(std::pair<T1, T2> const &pair, typename std::remove_const<T1>::type const &val) {
Run Code Online (Sandbox Code Playgroud)

但我不知道哪一个更合适,或者是否有其他解决方案更好.

Che*_*Alf 5

一种解决方案是使用std::add_const而不是const直接使用关键字.

通过模板的往返可以防止通过此参数类型进行类型推导:

#include <map>
#include <type_traits>
#include <utility>

template< class T1, class T2 >
void do_stuff( std::pair<T1, T2> const& pair, std::add_const_t<T1>& val )
{
    // Imagine that this does something important...
    (void) pair; (void) val;
}

auto main()
    -> int
{
    std::map<int, float> foo { { 0, 0.0f } };
    do_stuff(*foo.begin(), 0);
}
Run Code Online (Sandbox Code Playgroud)

  • "`auto main() - > int`"你这太过分了 (5认同)