簡體   English   中英

對沒有參數的可變參數模板函數的模糊調用?

[英]Ambiguous call to variadic template function with no parameters?

運行時:

template <typename T>
struct CodeByType
{
    static const int32_t Value = 7;
};

template <>
struct CodeByType<int>
{
    static const int32_t Value = 1;
};

template <typename Arg, typename... Args>
int32_t Sum()
{
    // The compiler complains on this line
    return Sum<Arg>() + Sum<Args...>();
}

template <typename Arg>
int32_t Sum()
{
    return CodeByType<Arg>::Value;
}

int main()
{
    auto sum = Sum<int, char, double>();
}

我越來越:

錯誤C2668'Sum':對重載函數的模糊調用

有人可以解釋為什么以及如何克服它?

這看起來非常類似於下面的代碼,它編譯,所以我想它與Sum不接受任何實際參數。

template <typename T>
T adder(T first) {
    return first;
}

template<typename T, typename... Args>
T adder(T first, Args... rest) {
    return first + adder(rest...);
}

int main()
{
    auto sum = adder(1, 7);
}

如果您將代碼簡化為:

Sum<int>();

您會收到更有用的錯誤消息:

 31 : <source>:31:16: error: call to 'Sum' is ambiguous auto sum = Sum<int>(); ^~~~~~~~ 17 : <source>:17:9: note: candidate function [with Arg = int, Args = <>] int32_t Sum() ^ 24 : <source>:24:9: note: candidate function [with Arg = int] int32_t Sum() ^ 1 error generated. 

因此更清楚的是,第一次重載與Args = <>和第二次重載之間存在過載模糊。 兩者都是可行的。

人們可能會認為解決方案的專業化:

template <typename Arg>
int32_t Sum<Arg>()
{
    return CodeByType<Arg>::Value;
}

如果標准允許,這確實可以解決問題。 不允許使用部分功能。

C ++ 17解決方案:

這是最優雅的解決方案:

constexpr如果要救援:

template <typename Arg, typename... Args>
int32_t Sum()
{
    if constexpr(sizeof...(Args) == 0)
      return CodeByType<Arg>::Value;
    else
      return Sum<Arg>() + Sum<Args...>();
}

C ++ 14解決方案

我們使用SFINAE來啟用/禁用我們想要的功能。 請注意,必須顛倒函數定義順序。

template <typename Arg, typename... Args>
auto Sum() -> std::enable_if_t<(sizeof...(Args) == 0), int32_t>
{
      return CodeByType<Arg>::Value;
}


template <typename Arg, typename... Args>
auto Sum() -> std::enable_if_t<(sizeof...(Args) > 0), int32_t>
{
      return Sum<Arg>() + Sum<Args...>();

}

C ++ 11解決方案

只需用typename std::enable_if<>::type替換std::enable_if_t<>

在c ++ 17中,它只是

template <typename... Args>
int32_t Sum()
{
    return (CodeByType<Args>::Value + ...); // Fold expression
}

在C ++ 11中,您可以:

template <typename... Args>
int32_t Sum()
{
    int32_t res = 0;
    const int32_t dummy[] = {0, (res += CodeByType<Args>::Value)...};
    static_cast<void>(dummy); silent warning about unused variable
    return res;
}

我對模板機制的記憶很老,但如果我沒記錯的話,他們的信息會在編譯過程中的某個時刻被刪除。

我的猜測是,在第二種情況下,函數不是通過模板類型的差異來區分,而是通過參數的差異來區分。

在您的情況下,您沒有參數,因此剝離了兩個重載版本相同的模板信息,並且在調用它時無法區分它們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM