简体   繁体   中英

I am getting " template argument deduction/substitution failed:" Error in C++

I have a C++ Code as Following:

#include <iostream>
using namespace std;

// Enter your code for reversed_binary_value<bool...>()
int reversed_binary_value()
{
    return 0;
}
template <bool i, bool... arg>
int reversed_binary_value()
{
    int z=0;
    z=reversed_binary_value(arg...)*2;
    if(i==0)
        return z;
    else
        return z+1;
}

template <int n, bool...digits>
struct CheckValues {
    static void check(int x, int y)
    {
        CheckValues<n-1, 0, digits...>::check(x, y);
        CheckValues<n-1, 1, digits...>::check(x, y);
    }
};

template <bool...digits>
struct CheckValues<0, digits...> {
    static void check(int x, int y)
    {
        int z = reversed_binary_value<digits...>();
        std::cout << (z+64*y==x);
    }
};

int main()
{
    int t; std::cin >> t;

    for (int i=0; i!=t; ++i) {
        int x, y;
        cin >> x >> y;
        CheckValues<6>::check(x, y);
        cout << "\n";
    }
}

I am getting "no matching function for call to 'reversed_binary_value(bool, bool, bool, bool, bool)" and then "template argument deduction/substitution failed:" This code is for the question on https://www.hackerrank.com/challenges/cpp-variadics/problem so I can not change the locked code

The error in your code is calling reversed_binary_value()

z=reversed_binary_value(arg...)*2;

that expect the boolean values a template parameters.

So you have to call it as follows

z=reversed_binary_value<arg...>()*2;
// ....................^......^^^

But now you have another problem: when the variadic pack args... is empty, the call become

z=reversed_binary_value<>()*2;

So you explicitly call a template function (the <> ), without template arguments, when your terminal reverse_binary_value() function

int reversed_binary_value()
{
    return 0;
}

isn't a template one.

I suggest you a dirty but useful trick: transform the terminal version in a template function that a accept something different from a value (maybe a type) and with a default argument; by example

template <typename = void>
int reversed_binary_value()
{
    return 0;
}

This way the final empty list call

z=reversed_binary_value<>()*2;

matches reverse_binary_value<void>() .

Another option to @max66's answer is to use enable_if to disable the recursive version for the special one-parameter case. This allows to unambiguously overload the function with another template:

template<bool b>
int reversed_binary_value()
{
    return b?1:0;
}

template <bool i=1, bool... arg>
std::enable_if_t<sizeof...(arg) != 0,int>
reversed_binary_value()
{
    int z=0;
    z=reversed_binary_value<arg...>()*2;
    if(i==0)
        return z;
    else
        return z+1;
}

If you want to be fancy(horrible?) with C++17 fold expressions, here is three-line solution:

template<bool...Args>
constexpr int reversed_binary_value(){
    int res=0,tmp=0;
    (tmp|=...|=((res*=2)+=Args));
    return res;
}

int main()
{
    static_assert(reversed_binary_value<1,1,1,1>()==15);
    static_assert(reversed_binary_value<0,1,0,1>()==10);
    static_assert(reversed_binary_value<1,0,0,1>()==9);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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