Why is Overload Resolution favoring unconstrained template function over a more specific one?function overload matching template template“Overload” function template based on function object operator() signature in C++98Overload resolution and partial template orderingWhy this function overloading fails in C++?Overloaded operator ambiguity on Clang but not on GCC, which one is correct?Error while operator overloading (error: no match for ‘operator<<’ (operand types are ‘std::basic_ostream<char>’ and ‘const char [2]’)C++ class template, how to overload [ ] operator in a specific stuation?Template template parameters - why are they needed in this case?C++11 ambiguous overload when calling variadic function templateAmbiguous Overload For operator “<<”

What is the theme of analysis?

Any gotchas in buying second-hand sanitary ware?

New Site Design!

Why did the Death Eaters wait to reopen the Chamber of Secrets?

What do I need to do, tax-wise, for a sudden windfall?

Print the phrase "And she said, 'But that's his.'" using only the alphabet

Can I get a photo of an Ancient Arrow?

What does the "titan" monster tag mean?

Why not make one big cpu core?

What game uses dice with compass point arrows, forbidden signs, explosions, arrows and targeting reticles?

DBCC SHRINKFILE on the distribution database

What's the reason for the decade jump in the recent X-Men trilogy?

Parsing text written the millitext font

Can an escape pod land on Earth from orbit and not be immediately detected?

Will users know a CardView is clickable

What is the color associated with lukewarm?

Parallelized for loop in Bash

Why is C++ template use not recommended in space/radiated environment?

Does every chapter have to "blow the reader away" so to speak?

How can this shape perfectly cover a cube?

I sent an angry e-mail to my interviewers about a conflict at my home institution. Could this affect my application?

Placement of positioning lights on A320 winglets

Interview was just a one hour panel. Got an offer the next day; do I accept or is this a red flag?

Loop counter not interpreted as number



Why is Overload Resolution favoring unconstrained template function over a more specific one?


function overload matching template template“Overload” function template based on function object operator() signature in C++98Overload resolution and partial template orderingWhy this function overloading fails in C++?Overloaded operator ambiguity on Clang but not on GCC, which one is correct?Error while operator overloading (error: no match for ‘operator<<’ (operand types are ‘std::basic_ostream<char>’ and ‘const char [2]’)C++ class template, how to overload [ ] operator in a specific stuation?Template template parameters - why are they needed in this case?C++11 ambiguous overload when calling variadic function templateAmbiguous Overload For operator “<<”






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








14















I have this minimal expression template library with a multiplication, i.e.



template <typename T, typename U>
struct mul
const T &v1;
const U &v2;
;

template <typename T, typename U>
mul<T, U> operator*(const T &one, const U &two)
std::cout << " called: mul<T, U> operator*(const T &one, const T &two)n";
return mul<T, U>one, two;



and transpose, i.e.



template <typename T>
struct transpose
const T &t;
;

template <typename T>
transpose<T> tran(const T &one)
return transpose<T>one;



I will introduce some types A and B, where the latter is a subclass of the former:



template <typename T>
struct A
T elem;
;

template <typename T>
struct B : A<T>
B(T val) : A<T>val
;


Then, I can call my expression template library as follows (with an overload for printing to std::cout):



template <typename T, typename U>
std::ostream &operator<<(std::ostream &os, const mul<T, U> &m)
os << " unconstrained template n";


int main(int argc, char const *argv[])
B<double> a2;
B<double> b3;
std::cout << tran(a) * b << "n";
return 0;



This gives me the output :



called: mul<T, U> operator*(const T &one, const T &two)
unconstrained template


So far so good. Suppose now that I want a specialized treatment for 'transpose of a variable of type A<T> times a variable of type A<T> for some type T', as I had in my main. To this end, I will introduce



template <typename T>
T operator*(const transpose<A<T>> &one, const A<T> &two)
std::cout << " called: T operator*(const A<T> &one, const A<T> &two)n";
return one.t.elem * two.elem;



I run the same main function as above, and I still get the same output as above (unconstrained template). This is to be expected, since transpose<B<double>> is a completely different type compared to transpose<A<double>>, so overload resolution picks the unconstrained template version of operator*.



(Of course, if I change my variable definitions in main to A instead of B, ADL calls the specialized function and output is called: T operator*(const A<T> &one, const A<T> &two) and 6).



I recently learned about SFINAE, so I expected the following change to the more specific multiplication operator would cause overload resulution to select the specialized function:



template <typename T, typename V>
std::enable_if_t<std::is_base_of<A<T>, V>::value, T> operator*(const transpose<V> &one,
const V &two)
std::cout << " called: std::enable_if_t<std::is_base_of<A<T>, V>::value, T> operator*(const "
"transpose<V> &one, const V &two)n";
return one.t.elem * two.elem;



Even using the SFINAE'd operator* I still get the unconstrained template version. How come? What changes should I make to call the more specialized template function?










share|improve this question
























  • Maybe my understanding of what ADL is is incorrect, but what this has to do with ADL?

    – Evg
    May 29 at 12:38











  • I thought 'Overload Resolution' and ADL are the same. Apparently, they're not.

    – Nibor
    May 29 at 13:10











  • Overloading resolution is choosing between names found incl. those found by ADL.

    – curiousguy
    Jun 6 at 5:49

















14















I have this minimal expression template library with a multiplication, i.e.



template <typename T, typename U>
struct mul
const T &v1;
const U &v2;
;

template <typename T, typename U>
mul<T, U> operator*(const T &one, const U &two)
std::cout << " called: mul<T, U> operator*(const T &one, const T &two)n";
return mul<T, U>one, two;



and transpose, i.e.



template <typename T>
struct transpose
const T &t;
;

template <typename T>
transpose<T> tran(const T &one)
return transpose<T>one;



I will introduce some types A and B, where the latter is a subclass of the former:



template <typename T>
struct A
T elem;
;

template <typename T>
struct B : A<T>
B(T val) : A<T>val
;


Then, I can call my expression template library as follows (with an overload for printing to std::cout):



template <typename T, typename U>
std::ostream &operator<<(std::ostream &os, const mul<T, U> &m)
os << " unconstrained template n";


int main(int argc, char const *argv[])
B<double> a2;
B<double> b3;
std::cout << tran(a) * b << "n";
return 0;



This gives me the output :



called: mul<T, U> operator*(const T &one, const T &two)
unconstrained template


So far so good. Suppose now that I want a specialized treatment for 'transpose of a variable of type A<T> times a variable of type A<T> for some type T', as I had in my main. To this end, I will introduce



template <typename T>
T operator*(const transpose<A<T>> &one, const A<T> &two)
std::cout << " called: T operator*(const A<T> &one, const A<T> &two)n";
return one.t.elem * two.elem;



I run the same main function as above, and I still get the same output as above (unconstrained template). This is to be expected, since transpose<B<double>> is a completely different type compared to transpose<A<double>>, so overload resolution picks the unconstrained template version of operator*.



(Of course, if I change my variable definitions in main to A instead of B, ADL calls the specialized function and output is called: T operator*(const A<T> &one, const A<T> &two) and 6).



I recently learned about SFINAE, so I expected the following change to the more specific multiplication operator would cause overload resulution to select the specialized function:



template <typename T, typename V>
std::enable_if_t<std::is_base_of<A<T>, V>::value, T> operator*(const transpose<V> &one,
const V &two)
std::cout << " called: std::enable_if_t<std::is_base_of<A<T>, V>::value, T> operator*(const "
"transpose<V> &one, const V &two)n";
return one.t.elem * two.elem;



Even using the SFINAE'd operator* I still get the unconstrained template version. How come? What changes should I make to call the more specialized template function?










share|improve this question
























  • Maybe my understanding of what ADL is is incorrect, but what this has to do with ADL?

    – Evg
    May 29 at 12:38











  • I thought 'Overload Resolution' and ADL are the same. Apparently, they're not.

    – Nibor
    May 29 at 13:10











  • Overloading resolution is choosing between names found incl. those found by ADL.

    – curiousguy
    Jun 6 at 5:49













14












14








14


1






I have this minimal expression template library with a multiplication, i.e.



template <typename T, typename U>
struct mul
const T &v1;
const U &v2;
;

template <typename T, typename U>
mul<T, U> operator*(const T &one, const U &two)
std::cout << " called: mul<T, U> operator*(const T &one, const T &two)n";
return mul<T, U>one, two;



and transpose, i.e.



template <typename T>
struct transpose
const T &t;
;

template <typename T>
transpose<T> tran(const T &one)
return transpose<T>one;



I will introduce some types A and B, where the latter is a subclass of the former:



template <typename T>
struct A
T elem;
;

template <typename T>
struct B : A<T>
B(T val) : A<T>val
;


Then, I can call my expression template library as follows (with an overload for printing to std::cout):



template <typename T, typename U>
std::ostream &operator<<(std::ostream &os, const mul<T, U> &m)
os << " unconstrained template n";


int main(int argc, char const *argv[])
B<double> a2;
B<double> b3;
std::cout << tran(a) * b << "n";
return 0;



This gives me the output :



called: mul<T, U> operator*(const T &one, const T &two)
unconstrained template


So far so good. Suppose now that I want a specialized treatment for 'transpose of a variable of type A<T> times a variable of type A<T> for some type T', as I had in my main. To this end, I will introduce



template <typename T>
T operator*(const transpose<A<T>> &one, const A<T> &two)
std::cout << " called: T operator*(const A<T> &one, const A<T> &two)n";
return one.t.elem * two.elem;



I run the same main function as above, and I still get the same output as above (unconstrained template). This is to be expected, since transpose<B<double>> is a completely different type compared to transpose<A<double>>, so overload resolution picks the unconstrained template version of operator*.



(Of course, if I change my variable definitions in main to A instead of B, ADL calls the specialized function and output is called: T operator*(const A<T> &one, const A<T> &two) and 6).



I recently learned about SFINAE, so I expected the following change to the more specific multiplication operator would cause overload resulution to select the specialized function:



template <typename T, typename V>
std::enable_if_t<std::is_base_of<A<T>, V>::value, T> operator*(const transpose<V> &one,
const V &two)
std::cout << " called: std::enable_if_t<std::is_base_of<A<T>, V>::value, T> operator*(const "
"transpose<V> &one, const V &two)n";
return one.t.elem * two.elem;



Even using the SFINAE'd operator* I still get the unconstrained template version. How come? What changes should I make to call the more specialized template function?










share|improve this question
















I have this minimal expression template library with a multiplication, i.e.



template <typename T, typename U>
struct mul
const T &v1;
const U &v2;
;

template <typename T, typename U>
mul<T, U> operator*(const T &one, const U &two)
std::cout << " called: mul<T, U> operator*(const T &one, const T &two)n";
return mul<T, U>one, two;



and transpose, i.e.



template <typename T>
struct transpose
const T &t;
;

template <typename T>
transpose<T> tran(const T &one)
return transpose<T>one;



I will introduce some types A and B, where the latter is a subclass of the former:



template <typename T>
struct A
T elem;
;

template <typename T>
struct B : A<T>
B(T val) : A<T>val
;


Then, I can call my expression template library as follows (with an overload for printing to std::cout):



template <typename T, typename U>
std::ostream &operator<<(std::ostream &os, const mul<T, U> &m)
os << " unconstrained template n";


int main(int argc, char const *argv[])
B<double> a2;
B<double> b3;
std::cout << tran(a) * b << "n";
return 0;



This gives me the output :



called: mul<T, U> operator*(const T &one, const T &two)
unconstrained template


So far so good. Suppose now that I want a specialized treatment for 'transpose of a variable of type A<T> times a variable of type A<T> for some type T', as I had in my main. To this end, I will introduce



template <typename T>
T operator*(const transpose<A<T>> &one, const A<T> &two)
std::cout << " called: T operator*(const A<T> &one, const A<T> &two)n";
return one.t.elem * two.elem;



I run the same main function as above, and I still get the same output as above (unconstrained template). This is to be expected, since transpose<B<double>> is a completely different type compared to transpose<A<double>>, so overload resolution picks the unconstrained template version of operator*.



(Of course, if I change my variable definitions in main to A instead of B, ADL calls the specialized function and output is called: T operator*(const A<T> &one, const A<T> &two) and 6).



I recently learned about SFINAE, so I expected the following change to the more specific multiplication operator would cause overload resulution to select the specialized function:



template <typename T, typename V>
std::enable_if_t<std::is_base_of<A<T>, V>::value, T> operator*(const transpose<V> &one,
const V &two)
std::cout << " called: std::enable_if_t<std::is_base_of<A<T>, V>::value, T> operator*(const "
"transpose<V> &one, const V &two)n";
return one.t.elem * two.elem;



Even using the SFINAE'd operator* I still get the unconstrained template version. How come? What changes should I make to call the more specialized template function?







c++ sfinae generic-programming expression-templates






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jun 6 at 3:49









Ratan Uday Kumar

1,30421533




1,30421533










asked May 29 at 12:24









NiborNibor

754421




754421












  • Maybe my understanding of what ADL is is incorrect, but what this has to do with ADL?

    – Evg
    May 29 at 12:38











  • I thought 'Overload Resolution' and ADL are the same. Apparently, they're not.

    – Nibor
    May 29 at 13:10











  • Overloading resolution is choosing between names found incl. those found by ADL.

    – curiousguy
    Jun 6 at 5:49

















  • Maybe my understanding of what ADL is is incorrect, but what this has to do with ADL?

    – Evg
    May 29 at 12:38











  • I thought 'Overload Resolution' and ADL are the same. Apparently, they're not.

    – Nibor
    May 29 at 13:10











  • Overloading resolution is choosing between names found incl. those found by ADL.

    – curiousguy
    Jun 6 at 5:49
















Maybe my understanding of what ADL is is incorrect, but what this has to do with ADL?

– Evg
May 29 at 12:38





Maybe my understanding of what ADL is is incorrect, but what this has to do with ADL?

– Evg
May 29 at 12:38













I thought 'Overload Resolution' and ADL are the same. Apparently, they're not.

– Nibor
May 29 at 13:10





I thought 'Overload Resolution' and ADL are the same. Apparently, they're not.

– Nibor
May 29 at 13:10













Overloading resolution is choosing between names found incl. those found by ADL.

– curiousguy
Jun 6 at 5:49





Overloading resolution is choosing between names found incl. those found by ADL.

– curiousguy
Jun 6 at 5:49












1 Answer
1






active

oldest

votes


















12














The problem is that in the SFINAE overload, T is used in a non-deduced context. You're effectively asking the compiler: "Enable this if there exists a T such that A<T> is a base class of V." Existential quantification is a good indicator that what you're asking for cannot be SFINAEd.



You can see this yourself if you disable the unconstrained template, as I did here. This forces the compiler to spell out why the other function is not admissible.



You can solve this by making T available through your A (and thus B) classes, like this:



template <typename T>
struct A
using Type = T;
T elem;
;


template <typename V>
std::enable_if_t<std::is_base_of<A<typename V::Type>, V>::value, typename V::Type> operator*(const transpose<V> &one,
const V &two)
std::cout << " called: std::enable_if_t<std::is_base_of<A<T>, V>::value, T> operator*(const "
"transpose<V> &one, const V &two)n";
return one.t.elem * two.elem;



[Live example]






share|improve this answer

























  • In fact removing the sfinae, the superfluous template argument then uncommenting the uncontrainted one yield me the correct result.

    – Guillaume Racicot
    May 29 at 12:35






  • 1





    @GuillaumeRacicot Yes, that works in the reduced example posted. But note that the OP says that the constrained version should only be used when V is derived from A<T> for some A. Removing the sfinae would make it apply to all transpose-nontranspose pairs.

    – Angew
    May 29 at 12:37











  • Reading this SFINAE it should only allow typename V to be B<T> but given that std::is_base_of<Base, Derived>::value yields true if std::is_same<Base, Derived>::value it also allows A<T>. Shouldn't there be a check to disallow that, too? If I am understand OP's Intention correctly, that is.

    – Stack Danny
    May 29 at 14:00












  • @StackDanny I understood the OP's question as "how do I word SFINAE for a special case that involves A<T> or a type derived from A<T>?" That's how I read "Suppose now that I want a specialized treatment for 'transpose of a variable of type A<T> times a variable of type A<T> for some type T', as I had in my main." Note that it was a B<double> in the main, actually.

    – Angew
    May 29 at 14:02












  • @Angew I just find it weird because if you were to remove struct B from the code the SFINAE (which strictly asks for a std::is_base_of case) will still be called even though there is no inheritance whatsover going on. I just thoughts that's unintentional. I suppose this is to be blamed on the implementation of std::is_base_of.

    – Stack Danny
    May 29 at 14:13












Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f56360583%2fwhy-is-overload-resolution-favoring-unconstrained-template-function-over-a-more%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









12














The problem is that in the SFINAE overload, T is used in a non-deduced context. You're effectively asking the compiler: "Enable this if there exists a T such that A<T> is a base class of V." Existential quantification is a good indicator that what you're asking for cannot be SFINAEd.



You can see this yourself if you disable the unconstrained template, as I did here. This forces the compiler to spell out why the other function is not admissible.



You can solve this by making T available through your A (and thus B) classes, like this:



template <typename T>
struct A
using Type = T;
T elem;
;


template <typename V>
std::enable_if_t<std::is_base_of<A<typename V::Type>, V>::value, typename V::Type> operator*(const transpose<V> &one,
const V &two)
std::cout << " called: std::enable_if_t<std::is_base_of<A<T>, V>::value, T> operator*(const "
"transpose<V> &one, const V &two)n";
return one.t.elem * two.elem;



[Live example]






share|improve this answer

























  • In fact removing the sfinae, the superfluous template argument then uncommenting the uncontrainted one yield me the correct result.

    – Guillaume Racicot
    May 29 at 12:35






  • 1





    @GuillaumeRacicot Yes, that works in the reduced example posted. But note that the OP says that the constrained version should only be used when V is derived from A<T> for some A. Removing the sfinae would make it apply to all transpose-nontranspose pairs.

    – Angew
    May 29 at 12:37











  • Reading this SFINAE it should only allow typename V to be B<T> but given that std::is_base_of<Base, Derived>::value yields true if std::is_same<Base, Derived>::value it also allows A<T>. Shouldn't there be a check to disallow that, too? If I am understand OP's Intention correctly, that is.

    – Stack Danny
    May 29 at 14:00












  • @StackDanny I understood the OP's question as "how do I word SFINAE for a special case that involves A<T> or a type derived from A<T>?" That's how I read "Suppose now that I want a specialized treatment for 'transpose of a variable of type A<T> times a variable of type A<T> for some type T', as I had in my main." Note that it was a B<double> in the main, actually.

    – Angew
    May 29 at 14:02












  • @Angew I just find it weird because if you were to remove struct B from the code the SFINAE (which strictly asks for a std::is_base_of case) will still be called even though there is no inheritance whatsover going on. I just thoughts that's unintentional. I suppose this is to be blamed on the implementation of std::is_base_of.

    – Stack Danny
    May 29 at 14:13
















12














The problem is that in the SFINAE overload, T is used in a non-deduced context. You're effectively asking the compiler: "Enable this if there exists a T such that A<T> is a base class of V." Existential quantification is a good indicator that what you're asking for cannot be SFINAEd.



You can see this yourself if you disable the unconstrained template, as I did here. This forces the compiler to spell out why the other function is not admissible.



You can solve this by making T available through your A (and thus B) classes, like this:



template <typename T>
struct A
using Type = T;
T elem;
;


template <typename V>
std::enable_if_t<std::is_base_of<A<typename V::Type>, V>::value, typename V::Type> operator*(const transpose<V> &one,
const V &two)
std::cout << " called: std::enable_if_t<std::is_base_of<A<T>, V>::value, T> operator*(const "
"transpose<V> &one, const V &two)n";
return one.t.elem * two.elem;



[Live example]






share|improve this answer

























  • In fact removing the sfinae, the superfluous template argument then uncommenting the uncontrainted one yield me the correct result.

    – Guillaume Racicot
    May 29 at 12:35






  • 1





    @GuillaumeRacicot Yes, that works in the reduced example posted. But note that the OP says that the constrained version should only be used when V is derived from A<T> for some A. Removing the sfinae would make it apply to all transpose-nontranspose pairs.

    – Angew
    May 29 at 12:37











  • Reading this SFINAE it should only allow typename V to be B<T> but given that std::is_base_of<Base, Derived>::value yields true if std::is_same<Base, Derived>::value it also allows A<T>. Shouldn't there be a check to disallow that, too? If I am understand OP's Intention correctly, that is.

    – Stack Danny
    May 29 at 14:00












  • @StackDanny I understood the OP's question as "how do I word SFINAE for a special case that involves A<T> or a type derived from A<T>?" That's how I read "Suppose now that I want a specialized treatment for 'transpose of a variable of type A<T> times a variable of type A<T> for some type T', as I had in my main." Note that it was a B<double> in the main, actually.

    – Angew
    May 29 at 14:02












  • @Angew I just find it weird because if you were to remove struct B from the code the SFINAE (which strictly asks for a std::is_base_of case) will still be called even though there is no inheritance whatsover going on. I just thoughts that's unintentional. I suppose this is to be blamed on the implementation of std::is_base_of.

    – Stack Danny
    May 29 at 14:13














12












12








12







The problem is that in the SFINAE overload, T is used in a non-deduced context. You're effectively asking the compiler: "Enable this if there exists a T such that A<T> is a base class of V." Existential quantification is a good indicator that what you're asking for cannot be SFINAEd.



You can see this yourself if you disable the unconstrained template, as I did here. This forces the compiler to spell out why the other function is not admissible.



You can solve this by making T available through your A (and thus B) classes, like this:



template <typename T>
struct A
using Type = T;
T elem;
;


template <typename V>
std::enable_if_t<std::is_base_of<A<typename V::Type>, V>::value, typename V::Type> operator*(const transpose<V> &one,
const V &two)
std::cout << " called: std::enable_if_t<std::is_base_of<A<T>, V>::value, T> operator*(const "
"transpose<V> &one, const V &two)n";
return one.t.elem * two.elem;



[Live example]






share|improve this answer















The problem is that in the SFINAE overload, T is used in a non-deduced context. You're effectively asking the compiler: "Enable this if there exists a T such that A<T> is a base class of V." Existential quantification is a good indicator that what you're asking for cannot be SFINAEd.



You can see this yourself if you disable the unconstrained template, as I did here. This forces the compiler to spell out why the other function is not admissible.



You can solve this by making T available through your A (and thus B) classes, like this:



template <typename T>
struct A
using Type = T;
T elem;
;


template <typename V>
std::enable_if_t<std::is_base_of<A<typename V::Type>, V>::value, typename V::Type> operator*(const transpose<V> &one,
const V &two)
std::cout << " called: std::enable_if_t<std::is_base_of<A<T>, V>::value, T> operator*(const "
"transpose<V> &one, const V &two)n";
return one.t.elem * two.elem;



[Live example]







share|improve this answer














share|improve this answer



share|improve this answer








edited May 29 at 14:38









Nicol Bolas

298k35499673




298k35499673










answered May 29 at 12:31









AngewAngew

138k11270362




138k11270362












  • In fact removing the sfinae, the superfluous template argument then uncommenting the uncontrainted one yield me the correct result.

    – Guillaume Racicot
    May 29 at 12:35






  • 1





    @GuillaumeRacicot Yes, that works in the reduced example posted. But note that the OP says that the constrained version should only be used when V is derived from A<T> for some A. Removing the sfinae would make it apply to all transpose-nontranspose pairs.

    – Angew
    May 29 at 12:37











  • Reading this SFINAE it should only allow typename V to be B<T> but given that std::is_base_of<Base, Derived>::value yields true if std::is_same<Base, Derived>::value it also allows A<T>. Shouldn't there be a check to disallow that, too? If I am understand OP's Intention correctly, that is.

    – Stack Danny
    May 29 at 14:00












  • @StackDanny I understood the OP's question as "how do I word SFINAE for a special case that involves A<T> or a type derived from A<T>?" That's how I read "Suppose now that I want a specialized treatment for 'transpose of a variable of type A<T> times a variable of type A<T> for some type T', as I had in my main." Note that it was a B<double> in the main, actually.

    – Angew
    May 29 at 14:02












  • @Angew I just find it weird because if you were to remove struct B from the code the SFINAE (which strictly asks for a std::is_base_of case) will still be called even though there is no inheritance whatsover going on. I just thoughts that's unintentional. I suppose this is to be blamed on the implementation of std::is_base_of.

    – Stack Danny
    May 29 at 14:13


















  • In fact removing the sfinae, the superfluous template argument then uncommenting the uncontrainted one yield me the correct result.

    – Guillaume Racicot
    May 29 at 12:35






  • 1





    @GuillaumeRacicot Yes, that works in the reduced example posted. But note that the OP says that the constrained version should only be used when V is derived from A<T> for some A. Removing the sfinae would make it apply to all transpose-nontranspose pairs.

    – Angew
    May 29 at 12:37











  • Reading this SFINAE it should only allow typename V to be B<T> but given that std::is_base_of<Base, Derived>::value yields true if std::is_same<Base, Derived>::value it also allows A<T>. Shouldn't there be a check to disallow that, too? If I am understand OP's Intention correctly, that is.

    – Stack Danny
    May 29 at 14:00












  • @StackDanny I understood the OP's question as "how do I word SFINAE for a special case that involves A<T> or a type derived from A<T>?" That's how I read "Suppose now that I want a specialized treatment for 'transpose of a variable of type A<T> times a variable of type A<T> for some type T', as I had in my main." Note that it was a B<double> in the main, actually.

    – Angew
    May 29 at 14:02












  • @Angew I just find it weird because if you were to remove struct B from the code the SFINAE (which strictly asks for a std::is_base_of case) will still be called even though there is no inheritance whatsover going on. I just thoughts that's unintentional. I suppose this is to be blamed on the implementation of std::is_base_of.

    – Stack Danny
    May 29 at 14:13

















In fact removing the sfinae, the superfluous template argument then uncommenting the uncontrainted one yield me the correct result.

– Guillaume Racicot
May 29 at 12:35





In fact removing the sfinae, the superfluous template argument then uncommenting the uncontrainted one yield me the correct result.

– Guillaume Racicot
May 29 at 12:35




1




1





@GuillaumeRacicot Yes, that works in the reduced example posted. But note that the OP says that the constrained version should only be used when V is derived from A<T> for some A. Removing the sfinae would make it apply to all transpose-nontranspose pairs.

– Angew
May 29 at 12:37





@GuillaumeRacicot Yes, that works in the reduced example posted. But note that the OP says that the constrained version should only be used when V is derived from A<T> for some A. Removing the sfinae would make it apply to all transpose-nontranspose pairs.

– Angew
May 29 at 12:37













Reading this SFINAE it should only allow typename V to be B<T> but given that std::is_base_of<Base, Derived>::value yields true if std::is_same<Base, Derived>::value it also allows A<T>. Shouldn't there be a check to disallow that, too? If I am understand OP's Intention correctly, that is.

– Stack Danny
May 29 at 14:00






Reading this SFINAE it should only allow typename V to be B<T> but given that std::is_base_of<Base, Derived>::value yields true if std::is_same<Base, Derived>::value it also allows A<T>. Shouldn't there be a check to disallow that, too? If I am understand OP's Intention correctly, that is.

– Stack Danny
May 29 at 14:00














@StackDanny I understood the OP's question as "how do I word SFINAE for a special case that involves A<T> or a type derived from A<T>?" That's how I read "Suppose now that I want a specialized treatment for 'transpose of a variable of type A<T> times a variable of type A<T> for some type T', as I had in my main." Note that it was a B<double> in the main, actually.

– Angew
May 29 at 14:02






@StackDanny I understood the OP's question as "how do I word SFINAE for a special case that involves A<T> or a type derived from A<T>?" That's how I read "Suppose now that I want a specialized treatment for 'transpose of a variable of type A<T> times a variable of type A<T> for some type T', as I had in my main." Note that it was a B<double> in the main, actually.

– Angew
May 29 at 14:02














@Angew I just find it weird because if you were to remove struct B from the code the SFINAE (which strictly asks for a std::is_base_of case) will still be called even though there is no inheritance whatsover going on. I just thoughts that's unintentional. I suppose this is to be blamed on the implementation of std::is_base_of.

– Stack Danny
May 29 at 14:13






@Angew I just find it weird because if you were to remove struct B from the code the SFINAE (which strictly asks for a std::is_base_of case) will still be called even though there is no inheritance whatsover going on. I just thoughts that's unintentional. I suppose this is to be blamed on the implementation of std::is_base_of.

– Stack Danny
May 29 at 14:13




















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f56360583%2fwhy-is-overload-resolution-favoring-unconstrained-template-function-over-a-more%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Wikipedia:Vital articles Мазмуну Biography - Өмүр баян Philosophy and psychology - Философия жана психология Religion - Дин Social sciences - Коомдук илимдер Language and literature - Тил жана адабият Science - Илим Technology - Технология Arts and recreation - Искусство жана эс алуу History and geography - Тарых жана география Навигация менюсу

Bruxelas-Capital Índice Historia | Composición | Situación lingüística | Clima | Cidades irmandadas | Notas | Véxase tamén | Menú de navegacióneO uso das linguas en Bruxelas e a situación do neerlandés"Rexión de Bruxelas Capital"o orixinalSitio da rexiónPáxina de Bruselas no sitio da Oficina de Promoción Turística de Valonia e BruxelasMapa Interactivo da Rexión de Bruxelas-CapitaleeWorldCat332144929079854441105155190212ID28008674080552-90000 0001 0666 3698n94104302ID540940339365017018237

What should I write in an apology letter, since I have decided not to join a company after accepting an offer letterShould I keep looking after accepting a job offer?What should I do when I've been verbally told I would get an offer letter, but still haven't gotten one after 4 weeks?Do I accept an offer from a company that I am not likely to join?New job hasn't confirmed starting date and I want to give current employer as much notice as possibleHow should I address my manager in my resignation letter?HR delayed background verification, now jobless as resignedNo email communication after accepting a formal written offer. How should I phrase the call?What should I do if after receiving a verbal offer letter I am informed that my written job offer is put on hold due to some internal issues?Should I inform the current employer that I am about to resign within 1-2 weeks since I have signed the offer letter and waiting for visa?What company will do, if I send their offer letter to another company