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 “<<”

Will users know a CardView is clickable

Would a character with eternal youth be AL-compliant?

Does WiFi affect the quality of images downloaded from the internet?

Should I move out from my current apartment before the contract ends to save more money?

What publication claimed that Michael Jackson died in a nuclear holocaust?

Why not make one big cpu core?

Am I being scammed by a sugar daddy?

Why did Robert pick unworthy men for the White Cloaks?

What is the theme of analysis?

In The Incredibles 2, why does Screenslaver's name use a pun on something that doesn't exist in the 1950s pastiche?

Difference between grep -R and -r

How can this shape perfectly cover a cube?

Is fission/fusion to iron the most efficient way to convert mass to energy?

Can I get a photo of an Ancient Arrow?

Would a bit of grease on overhead door cables or bearings cause the springs to break?

Should I worry about having my credit pulled multiple times while car shopping?

Commencez à vous connecter -- I don't understand the phrasing of this

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

Realistic, logical way for men with medieval-era weaponry to compete with much larger and physically stronger foes

A flower's head or heart?

Can an open source licence be revoked if it violates employer's IP?

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

Optimising matrix generation time

Is it a good security practice to force employees hide their employer to avoid being targeted?



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 - Тарых жана география Навигация менюсу

Club Baloncesto Breogán Índice Historia | Pavillón | Nome | O Breogán na cultura popular | Xogadores | Adestradores | Presidentes | Palmarés | Historial | Líderes | Notas | Véxase tamén | Menú de navegacióncbbreogan.galCadroGuía oficial da ACB 2009-10, páxina 201Guía oficial ACB 1992, páxina 183. Editorial DB.É de 6.500 espectadores sentados axeitándose á última normativa"Estudiantes Junior, entre as mellores canteiras"o orixinalHemeroteca El Mundo Deportivo, 16 setembro de 1970, páxina 12Historia do BreogánAlfredo Pérez, o último canoneiroHistoria C.B. BreogánHemeroteca de El Mundo DeportivoJimmy Wright, norteamericano do Breogán deixará Lugo por ameazas de morteResultados de Breogán en 1986-87Resultados de Breogán en 1990-91Ficha de Velimir Perasović en acb.comResultados de Breogán en 1994-95Breogán arrasa al Barça. "El Mundo Deportivo", 27 de setembro de 1999, páxina 58CB Breogán - FC BarcelonaA FEB invita a participar nunha nova Liga EuropeaCharlie Bell na prensa estatalMáximos anotadores 2005Tempada 2005-06 : Tódolos Xogadores da Xornada""Non quero pensar nunha man negra, mais pregúntome que está a pasar""o orixinalRaúl López, orgulloso dos xogadores, presume da boa saúde económica do BreogánJulio González confirma que cesa como presidente del BreogánHomenaxe a Lisardo GómezA tempada do rexurdimento celesteEntrevista a Lisardo GómezEl COB dinamita el Pazo para forzar el quinto (69-73)Cafés Candelas, patrocinador del CB Breogán"Suso Lázare, novo presidente do Breogán"o orixinalCafés Candelas Breogán firma el mayor triunfo de la historiaEl Breogán realizará 17 homenajes por su cincuenta aniversario"O Breogán honra ao seu fundador e primeiro presidente"o orixinalMiguel Giao recibiu a homenaxe do PazoHomenaxe aos primeiros gladiadores celestesO home que nos amosa como ver o Breo co corazónTita Franco será homenaxeada polos #50anosdeBreoJulio Vila recibirá unha homenaxe in memoriam polos #50anosdeBreo"O Breogán homenaxeará aos seus aboados máis veteráns"Pechada ovación a «Capi» Sanmartín e Ricardo «Corazón de González»Homenaxe por décadas de informaciónPaco García volve ao Pazo con motivo do 50 aniversario"Resultados y clasificaciones""O Cafés Candelas Breogán, campión da Copa Princesa""O Cafés Candelas Breogán, equipo ACB"C.B. Breogán"Proxecto social"o orixinal"Centros asociados"o orixinalFicha en imdb.comMario Camus trata la recuperación del amor en 'La vieja música', su última película"Páxina web oficial""Club Baloncesto Breogán""C. B. Breogán S.A.D."eehttp://www.fegaba.com

Vilaño, A Laracha Índice Patrimonio | Lugares e parroquias | Véxase tamén | Menú de navegación43°14′52″N 8°36′03″O / 43.24775, -8.60070