Home > Software design >  Template function deduction fail on std::conditional argument
Template function deduction fail on std::conditional argument

Time:05-19

Please, before marking this as a duplicate of This question read the entirety of the post

This piece of code fails to compile, with a template deduction error:

#include <iostream>
#include <type_traits>

template<typename T = float, int N>
class MyClass
{
    public:
        template<typename DATA_TYPE>
        using MyType = std::conditional_t<(N>0), DATA_TYPE, double>;
        
        MyType<T> Var;
        
        void Foo()
        {
           Bar(Var);
        }
        
        template<typename TYPE>
        void Bar(MyType<TYPE> Input)
        {
            std::cout << typeid(Input).name() << std::endl;
        }
};

int main()
{
    MyClass<float, 1> c;
    c.Foo();
    return 0;
}

I understand the point that was made in the question i linked above, which is that "the condition which allows to choose the type to be deduced depends on the type itself", however, why would the compiler fail in the specific case i provided as the condition here seems to be fully independent from the type, or is there something i'm missing?

I would be more than happy if someone could refer to a section of the c standard that would allow me to fully understand this behaviour.

CodePudding user response:

As the linked question, TYPE is non deducible. MyType<TYPE> is actually XXX<TYPE>::type.

You have several alternatives, from your code, I would say one of

  • Bar no longer template:

    template<typename T = float, int N>
    class MyClass
    {
        public:
            template<typename DATA_TYPE>
            using MyType = std::conditional_t<(N>0), DATA_TYPE, double>;
    
            MyType<T> Var;
    
            void Foo()
            {
               Bar(Var);
            }
    
            void Bar(MyType<T> Input)
            {
                std::cout << typeid(Input).name() << std::endl;
            }
    };
    
  • requires (or SFINAE/specialization for pre-c 20):

    template<typename T = float, int N>
    class MyClass
    {
        public:
            template<typename DATA_TYPE>
            using MyType = std::conditional_t<(N>0), DATA_TYPE, double>;
    
            MyType<T> Var;
    
            void Foo()
            {
               Bar(Var);
            }
    
            template<typename TYPE>
            void Bar(TYPE Input) requires(N > 0)
            {
                std::cout << typeid(Input).name() << std::endl;
            }
            void Bar(double Input) requires(N <= 0)
            {
                std::cout << typeid(Input).name() << std::endl;
            }
    };
    
  • Related