【问题标题】:rvalue argument cannot resolve in function overload右值参数无法在函数重载中解析
【发布时间】:2017-12-16 02:05:14
【问题描述】:

如何编译main() 的最后一行?

#include <initializer_list>
#include <type_traits>
#include <functional>

template <typename T>
struct foo {
    foo(std::initializer_list<T>) { }

    template <typename C> struct is_foo : std::false_type { };
    template <typename U> struct is_foo<foo<U>> : std::true_type { };

    template <typename Compare>
    std::enable_if_t<!is_foo<Compare>::value> bar(foo&, Compare comp) {
        bool b = comp(T(), T());  // This line compiles thanks to is_foo<Compare>.
    }

    void bar(foo&& f) { bar(std::forward<foo>(f), std::less<T>()); }

    template <typename... Foos>
    void bar(Foos&&...) { }
};

int main() {
    foo<int> f = {1,2,3};
    f.bar({4,5,6});  // Compiles fine
    f.bar(f,f);  // Compiles fine (thanks to is_foo<Compare>)
    f.bar(f,{4,5,6});  // Won't compile
}

应该调用foo&lt;T&gt;::bar(Foos&amp;&amp;...)

Test.cpp:27:17: error: no matching function for call to 'foo<int>::bar(foo<int>&, <brace-enclosed initializer list>)'
  f.bar(f,{4,5,6});  // Won't compile
                 ^
Test.cpp:13:44: note: candidate: template<class Compare> std::enable_if_t<(! foo<T>::is_foo<C>::value)> foo<T>::bar(foo<T>&, Compare) [with Compare = Compare; T = int]
  std::enable_if_t<!is_foo<Compare>::value> bar(foo&, Compare comp) {
                                            ^~~
Test.cpp:13:44: note:   template argument deduction/substitution failed:
Test.cpp:27:17: note:   couldn't deduce template parameter 'Compare'
  f.bar(f,{4,5,6});

【问题讨论】:

  • 不幸的是,大括号初始化列表无法匹配转发引用。一个花括号初始化器列表“需要知道”它正在初始化什么。转发引用也需要知道它在转发什么。没人知道它到底应该是什么。
  • 最简单的方法是使用简单的 foo cast

标签: c++ c++11 variadic-templates overloading rvalue-reference


【解决方案1】:

不确定您到底想要什么,但是,如果您的意图是获得一个可变参数 bar() 函数,该函数接收零个或多个 foo&lt;T&gt; 参数(或可用于初始化 foo&lt;T&gt; 的参数),那么。 ..如果您接受参数数量的限制(例如 63,在下面的示例中),则 WF 有一个技巧showed one time 我想可以适应你的情况。

如果你定义了typer 模板别名

template <typename T, std::size_t>
using typer = T;

还有一个递归的struct proBar

template <typename T, std::size_t N = 64U,
          typename = std::make_index_sequence<N>>
struct proBar;

template <typename T, std::size_t N, std::size_t... Is>
struct proBar<T, N, std::index_sequence<Is...>> : public proBar<T, N-1U>
 {
   using proBar<T, N-1U>::bar;

   void bar (typer<T, Is>... ts)
    { }
 };

template <typename T>
struct proBar<T, 0U, std::index_sequence<>>
 {
    void bar ()
     { }
 };

允许定义你需要的bar()函数,你的模板struct foo变成

template <typename T>
struct foo : public proBar<foo<T>>
 {
   using proBar<foo<T>>::bar;

   foo (std::initializer_list<T>)
    { }

   template <typename Compare>
   auto bar (foo &, Compare comp) -> decltype(comp(T(), T()), void())
    { bool b = comp(T(), T()); }
 };

以下是完整的编译示例

#include <initializer_list>

template <typename T, std::size_t>
using typer = T;

template <typename T, std::size_t N = 64U,
          typename = std::make_index_sequence<N>>
struct proBar;

template <typename T, std::size_t N, std::size_t... Is>
struct proBar<T, N, std::index_sequence<Is...>> : public proBar<T, N-1U>
 {
   using proBar<T, N-1U>::bar;

   void bar (typer<T, Is>... ts)
    { }
 };

template <typename T>
struct proBar<T, 0U, std::index_sequence<>>
 {
    void bar ()
     { }
 };

template <typename T>
struct foo : public proBar<foo<T>>
 {
   using proBar<foo<T>>::bar;

   foo (std::initializer_list<T>)
    { }

   template <typename Compare>
   auto bar (foo &, Compare comp) -> decltype(comp(T(), T()), void())
    { bool b = comp(T(), T()); }
 };



int main()
 {
   foo<int> f = {1, 2, 3};
   f.bar({4, 5, 6});
   f.bar(f, f);
   f.bar(f, {4, 5, 6}); // now compile
 }

【讨论】:

  • 感谢激进的解决方案。如果proBar&lt;foo&lt;T&gt;&gt;::bar 的定义主体中需要foo&lt;T&gt;this)的成员,CRTP 会起作用(并且需要)吗?我想我应该试试看。
  • @prestokeys - 回答有所改进(我认为):我已经修改了比较 bar() 版本,通过 SFINAE 使用 autodecltype() 而不是 isFoo 启用它(并删除了isFoo)。
【解决方案2】:

这行得通。

#include <initializer_list>
#include <type_traits>
#include <functional>

template <typename T>
struct foo {
    foo(std::initializer_list<T>) { }

    template <typename C> struct is_foo : std::false_type { };
    template <typename U> struct is_foo<foo<U>> : std::true_type { };

    template <typename Compare>
    std::enable_if_t<!is_foo<Compare>::value> bar(foo&, Compare comp) {
        bool b = comp(T(), T());  // This line compiles thanks to is_foo<Compare>.
    }

    void bar(foo&& f) { bar(std::forward<foo>(f), std::less<T>()); }

    template <typename... Foos>
    void bar(Foos&&...) { }
};

int main() {
    foo<int> f = { 1,2,3 };
    f.bar({ 4,5,6 });  // Compiles fine
    f.bar(f, f);  // Compiles fine (thanks to is_foo<Compare>)
    f.bar(f, foo<int>({ 4,5,6 }));  // Won't compile
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-24
    • 1970-01-01
    • 2015-11-08
    • 2022-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多