Search code examples
c++c++14variadic-templatesvariadic-functions

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


Solution

  • 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>().