简体   繁体   中英

template function argument explicit type declaration

I have a list of operator overloads, and I found that they are not acting in the way that I want them to. I reduced the problematic code to a couple lines to simulate the problem. I have a couple template type aliases to help compile time decision making, a template function (an operator in the working code, but here just a generic function), and a class called var that takes in two template parameters, an unsigned int and a bool ( true = known var, false = unknown var, just mentioning this so that the naming convention in the following code snippet makes sense). Here is the code.

template<typename T>
using is_known = typename std::is_same<T, const var<T::ID, true> >::type;

template<typename T>
using is_unknown = typename std::conditional<is_known<T>::value, std::false_type, std::true_type>::type;

template<typename T>
using UK_if_UK = typename std::enable_if<is_unknown<T>::value, T>::type;

template<typename unknown_check_LHS, typename unknown_check_RHS>
constexpr const two_param_type<UK_if_UK<unknown_check_LHS>, UK_if_UK<unknown_check_RHS> > func(const unknown_check_LHS& lhs, const unknown_check_RHS& rhs)
{
    return two_param_type<unknown_check_LHS, unknown_check_RHS>
    (//generic construction goes here, unimportant...);
}

int main()
{
    constexpr const var<0u,true> firstvar(123);
    constexpr const var<1u,true> secondvar(456);

    func(firstvar,secondvar);
    func<std::decltype(firstvar),std::decltype(secondvar)>(firstvar,secondvar);
}

The two calls to func() seem identical to me, and they should both fail (in the working code there are other options once this function SFINAEs out). However, only the second call, where I explicitly declare the types, does the compiler throw an error. It compiles the first call to func() perfectly, and even worse, it operates and returns with type "known" ( var<(some unsigned),true> ), even though the type alias in the return type should SFINAE the function out of overload resolution. I am using operators, so explicitly declaring the type is not an option for me. More importantly, however, I want to know why the function is not SFINAEing out. Any help would be appreciated. Thank you.

Note: The specific error is:

error: no matching function for call to 'func(const var<0u, true>&, const var<1u, true>&)'

Also, I have tested is_known , is_unknown , and UK_if_UK to work properly, so no need to test those. Thank you.

The two calls to func seem identical to me

Wrong.

They are different.

It's a constness problem.

With

constexpr const var<0u,true> firstvar(123);
constexpr const var<1u,true> secondvar(456);

and the signature of func() as follows

template<typename unknown_check_LHS, typename unknown_check_RHS>
constexpr /* ... */ func (const unknown_check_LHS & lhs,
                          const unknown_check_RHS & rhs)

calling

func(firstvar,secondvar);

the types, unknown_check_LHS and unknown_check_RHS , are detected as var<0u, true> and var<1u, true> respectively.

Please observe: var<0u, true> and var<1u, true> , not const var<0u, true> and const var<1u, true> .

On the contrary, explicating the types as follows

func<decltype(firstvar), decltype(secondvar)>(firstvar,secondvar);

(and please: decltype() , not std::decltype() ), unknown_check_LHS and unknown_check_RHS are explicated as const var<0u, true> and const var<1u, true> respectively.

Observe that now the types are constant .

Observe how is defined is_know

template<typename T>
using is_known = typename std::is_same<T, const var<T::ID, true> >::type;

It compare the type T with a constant type.

So, in the first case (with template types not-constant), is_known is false; in the second case (with constant template types), it's true.

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