Is there a c++ trait to find the most restricted type between two types in C++?
I would like a type trait common
so that
common<int,int>::type -> int
common<const int, int>::type -> const int
common<int, int &>::type -> int
common<int &, int &>::type -> int &
common<int &, int const &>::type -> int const &
that is the result type should be the more restricted of the two. Is there a trait in the C++11 std that can do this or do I have to roll my own?
My use case is that I have a something similar to
template <typename T0, typename T1>
struct Foo {
BOOST_STATIC_ASSERT(
std::is_same
< typename std::decay<T0>::type
, typename std::decay<T1>::type
>::value
);
// I need to find T which is the most restrictive common
// type between T0 and T1
typedef typename common<T0,T1>::type T
T0 t0;
T1 t1;
T choose(bool c){
return c ? t0 : t1;
}
}
c++ c++11 templates typetraits
add a comment |
I would like a type trait common
so that
common<int,int>::type -> int
common<const int, int>::type -> const int
common<int, int &>::type -> int
common<int &, int &>::type -> int &
common<int &, int const &>::type -> int const &
that is the result type should be the more restricted of the two. Is there a trait in the C++11 std that can do this or do I have to roll my own?
My use case is that I have a something similar to
template <typename T0, typename T1>
struct Foo {
BOOST_STATIC_ASSERT(
std::is_same
< typename std::decay<T0>::type
, typename std::decay<T1>::type
>::value
);
// I need to find T which is the most restrictive common
// type between T0 and T1
typedef typename common<T0,T1>::type T
T0 t0;
T1 t1;
T choose(bool c){
return c ? t0 : t1;
}
}
c++ c++11 templates typetraits
add a comment |
I would like a type trait common
so that
common<int,int>::type -> int
common<const int, int>::type -> const int
common<int, int &>::type -> int
common<int &, int &>::type -> int &
common<int &, int const &>::type -> int const &
that is the result type should be the more restricted of the two. Is there a trait in the C++11 std that can do this or do I have to roll my own?
My use case is that I have a something similar to
template <typename T0, typename T1>
struct Foo {
BOOST_STATIC_ASSERT(
std::is_same
< typename std::decay<T0>::type
, typename std::decay<T1>::type
>::value
);
// I need to find T which is the most restrictive common
// type between T0 and T1
typedef typename common<T0,T1>::type T
T0 t0;
T1 t1;
T choose(bool c){
return c ? t0 : t1;
}
}
c++ c++11 templates typetraits
I would like a type trait common
so that
common<int,int>::type -> int
common<const int, int>::type -> const int
common<int, int &>::type -> int
common<int &, int &>::type -> int &
common<int &, int const &>::type -> int const &
that is the result type should be the more restricted of the two. Is there a trait in the C++11 std that can do this or do I have to roll my own?
My use case is that I have a something similar to
template <typename T0, typename T1>
struct Foo {
BOOST_STATIC_ASSERT(
std::is_same
< typename std::decay<T0>::type
, typename std::decay<T1>::type
>::value
);
// I need to find T which is the most restrictive common
// type between T0 and T1
typedef typename common<T0,T1>::type T
T0 t0;
T1 t1;
T choose(bool c){
return c ? t0 : t1;
}
}
c++ c++11 templates typetraits
c++ c++11 templates typetraits
edited Nov 21 '18 at 12:24
max66
36.4k74165
36.4k74165
asked Nov 21 '18 at 9:50
bradgonesurfingbradgonesurfing
16.3k1083151
16.3k1083151
add a comment |
add a comment |
4 Answers
4
active
oldest
votes
I am afraid that you need to roll your own. You can warp your types in a std::tuple, then pass it to std::common_type
, e.g.
#include <tuple>
#include <type_traits>
template <class T1, class T2>
struct common {
using type = typename std::tuple_element<0, typename std::common_type<std::tuple<T1>, std::tuple<T2>>::type>::type;
};
template <class T>
struct common<const T, T> {
using type = const T;
};
template <class T>
struct common<T, const T> {
using type = const T;
};
template <class T>
struct common<const T, const T> {
using type = const T;
};
int main()
{
static_assert(std::is_same<common<int, int>::type, int>::value, "");
static_assert(std::is_same<common<const int, int>::type, const int>::value, "");
static_assert(std::is_same<common<int, int &>::type, int>::value, "");
static_assert(std::is_same<common<int &, int &>::type, int &>::value, "");
static_assert(std::is_same<common<int &, int const &>::type, int const &>::value, "");
return 0;
}
But you have to create special cases for const
.
add a comment |
Taking inspiration from Oliv's solution, a possible C++11 version
#include <utility>
#include <type_traits>
template <typename T1, typename T2>
using cond_t = decltype(false ? std::declval<T1>() : std::declval<T2>());
template <typename T1, typename T2>
using common = typename std::conditional<
std::is_reference<T1>::value || std::is_reference<T2>::value,
cond_t<T1, T2>,
typename std::remove_reference<cond_t<T1 &, T2 &>>::type>::type;
int main()
{
using t1 = common<int,int>;
using t2 = common<const int, int>;
using t3 = common<int, int &>;
using t4 = common<int &, int &>;
using t5 = common<int &, int const &>;
static_assert( std::is_same<t1, int>::value, "!" );
static_assert( std::is_same<t2, int const>::value, "!" );
static_assert( std::is_same<t3, int>::value, "!" );
static_assert( std::is_same<t4, int &>::value, "!" );
static_assert( std::is_same<t5, int const &>::value, "!" );
}
I would have selected this as the as the answer but it doesn't work for my version of visual studio. Still a good answer :) Upvoted
– bradgonesurfing
Nov 21 '18 at 11:36
add a comment |
In c++20 you could use common_reference
, (there is an implementation in the range v3 library), but it needs some adaptation if none of the two types are reference:
template<class T,class U>
using common_t = conditional_t<is_reference_v<T> || is_reference_v<U>
,common_reference_t<T,U>
,remove_reference_t<common_reference_t<T&,U&>>>;
I need the solution for visual studio 2010 upwards but the answer is good info anyway :)
– bradgonesurfing
Nov 21 '18 at 10:27
add a comment |
This can be hacked with decltype
https://godbolt.org/z/7xEv7Z
#include <type_traits>
// Use it to display the actual generated type
template <typename T> struct F;
template <typename T0,typename T1>
struct Common
{
typedef decltype(true ? ((T0)std::declval<T0>()) : ((T1)std::declval<T1>()) )
type;
};
// Perform tests
F<Common<int,int>::type> f0;
F<Common<int &,int>::type> f1;
F<Common<const int &, int &>::type> f2;
F<Common<const int &, int>::type> f3;
Gives the results as expected
aggregate 'F<int> f0' has incomplete type and cannot be defined
aggregate 'F<int> f1' has incomplete type and
aggregate 'F<const int&> f2' has incomplete
aggregate 'F<int> f3' has incomplete type and
I believe this will not give you the desired result for the casecommon<int, int>::type
as declval will always return a reference and the deduced type is, thus, going to be a reference…
– Michael Kenzel
Nov 21 '18 at 10:23
@MichaelKenzel: I thought I saw your answer here before. Why did you delete it?
– P.W
Nov 21 '18 at 10:26
You are right.int,int
give rvalue reference
– bradgonesurfing
Nov 21 '18 at 10:26
@P.W my answer was simply to usestd::common_type
which is, unfortunately, not correct asstd::common_type
will decay the arguments and just return plainint
in all the cases above…
– Michael Kenzel
Nov 21 '18 at 10:30
@MichaelKenzel A small fix to using decltype will make it work. Just need to C style cast the result of decltype back to the type we want. I fixed the solution
– bradgonesurfing
Nov 21 '18 at 10:41
|
show 6 more comments
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53409292%2fis-there-a-c-trait-to-find-the-most-restricted-type-between-two-types-in-c%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
I am afraid that you need to roll your own. You can warp your types in a std::tuple, then pass it to std::common_type
, e.g.
#include <tuple>
#include <type_traits>
template <class T1, class T2>
struct common {
using type = typename std::tuple_element<0, typename std::common_type<std::tuple<T1>, std::tuple<T2>>::type>::type;
};
template <class T>
struct common<const T, T> {
using type = const T;
};
template <class T>
struct common<T, const T> {
using type = const T;
};
template <class T>
struct common<const T, const T> {
using type = const T;
};
int main()
{
static_assert(std::is_same<common<int, int>::type, int>::value, "");
static_assert(std::is_same<common<const int, int>::type, const int>::value, "");
static_assert(std::is_same<common<int, int &>::type, int>::value, "");
static_assert(std::is_same<common<int &, int &>::type, int &>::value, "");
static_assert(std::is_same<common<int &, int const &>::type, int const &>::value, "");
return 0;
}
But you have to create special cases for const
.
add a comment |
I am afraid that you need to roll your own. You can warp your types in a std::tuple, then pass it to std::common_type
, e.g.
#include <tuple>
#include <type_traits>
template <class T1, class T2>
struct common {
using type = typename std::tuple_element<0, typename std::common_type<std::tuple<T1>, std::tuple<T2>>::type>::type;
};
template <class T>
struct common<const T, T> {
using type = const T;
};
template <class T>
struct common<T, const T> {
using type = const T;
};
template <class T>
struct common<const T, const T> {
using type = const T;
};
int main()
{
static_assert(std::is_same<common<int, int>::type, int>::value, "");
static_assert(std::is_same<common<const int, int>::type, const int>::value, "");
static_assert(std::is_same<common<int, int &>::type, int>::value, "");
static_assert(std::is_same<common<int &, int &>::type, int &>::value, "");
static_assert(std::is_same<common<int &, int const &>::type, int const &>::value, "");
return 0;
}
But you have to create special cases for const
.
add a comment |
I am afraid that you need to roll your own. You can warp your types in a std::tuple, then pass it to std::common_type
, e.g.
#include <tuple>
#include <type_traits>
template <class T1, class T2>
struct common {
using type = typename std::tuple_element<0, typename std::common_type<std::tuple<T1>, std::tuple<T2>>::type>::type;
};
template <class T>
struct common<const T, T> {
using type = const T;
};
template <class T>
struct common<T, const T> {
using type = const T;
};
template <class T>
struct common<const T, const T> {
using type = const T;
};
int main()
{
static_assert(std::is_same<common<int, int>::type, int>::value, "");
static_assert(std::is_same<common<const int, int>::type, const int>::value, "");
static_assert(std::is_same<common<int, int &>::type, int>::value, "");
static_assert(std::is_same<common<int &, int &>::type, int &>::value, "");
static_assert(std::is_same<common<int &, int const &>::type, int const &>::value, "");
return 0;
}
But you have to create special cases for const
.
I am afraid that you need to roll your own. You can warp your types in a std::tuple, then pass it to std::common_type
, e.g.
#include <tuple>
#include <type_traits>
template <class T1, class T2>
struct common {
using type = typename std::tuple_element<0, typename std::common_type<std::tuple<T1>, std::tuple<T2>>::type>::type;
};
template <class T>
struct common<const T, T> {
using type = const T;
};
template <class T>
struct common<T, const T> {
using type = const T;
};
template <class T>
struct common<const T, const T> {
using type = const T;
};
int main()
{
static_assert(std::is_same<common<int, int>::type, int>::value, "");
static_assert(std::is_same<common<const int, int>::type, const int>::value, "");
static_assert(std::is_same<common<int, int &>::type, int>::value, "");
static_assert(std::is_same<common<int &, int &>::type, int &>::value, "");
static_assert(std::is_same<common<int &, int const &>::type, int const &>::value, "");
return 0;
}
But you have to create special cases for const
.
edited Nov 21 '18 at 10:39
answered Nov 21 '18 at 10:17
felixfelix
1,473314
1,473314
add a comment |
add a comment |
Taking inspiration from Oliv's solution, a possible C++11 version
#include <utility>
#include <type_traits>
template <typename T1, typename T2>
using cond_t = decltype(false ? std::declval<T1>() : std::declval<T2>());
template <typename T1, typename T2>
using common = typename std::conditional<
std::is_reference<T1>::value || std::is_reference<T2>::value,
cond_t<T1, T2>,
typename std::remove_reference<cond_t<T1 &, T2 &>>::type>::type;
int main()
{
using t1 = common<int,int>;
using t2 = common<const int, int>;
using t3 = common<int, int &>;
using t4 = common<int &, int &>;
using t5 = common<int &, int const &>;
static_assert( std::is_same<t1, int>::value, "!" );
static_assert( std::is_same<t2, int const>::value, "!" );
static_assert( std::is_same<t3, int>::value, "!" );
static_assert( std::is_same<t4, int &>::value, "!" );
static_assert( std::is_same<t5, int const &>::value, "!" );
}
I would have selected this as the as the answer but it doesn't work for my version of visual studio. Still a good answer :) Upvoted
– bradgonesurfing
Nov 21 '18 at 11:36
add a comment |
Taking inspiration from Oliv's solution, a possible C++11 version
#include <utility>
#include <type_traits>
template <typename T1, typename T2>
using cond_t = decltype(false ? std::declval<T1>() : std::declval<T2>());
template <typename T1, typename T2>
using common = typename std::conditional<
std::is_reference<T1>::value || std::is_reference<T2>::value,
cond_t<T1, T2>,
typename std::remove_reference<cond_t<T1 &, T2 &>>::type>::type;
int main()
{
using t1 = common<int,int>;
using t2 = common<const int, int>;
using t3 = common<int, int &>;
using t4 = common<int &, int &>;
using t5 = common<int &, int const &>;
static_assert( std::is_same<t1, int>::value, "!" );
static_assert( std::is_same<t2, int const>::value, "!" );
static_assert( std::is_same<t3, int>::value, "!" );
static_assert( std::is_same<t4, int &>::value, "!" );
static_assert( std::is_same<t5, int const &>::value, "!" );
}
I would have selected this as the as the answer but it doesn't work for my version of visual studio. Still a good answer :) Upvoted
– bradgonesurfing
Nov 21 '18 at 11:36
add a comment |
Taking inspiration from Oliv's solution, a possible C++11 version
#include <utility>
#include <type_traits>
template <typename T1, typename T2>
using cond_t = decltype(false ? std::declval<T1>() : std::declval<T2>());
template <typename T1, typename T2>
using common = typename std::conditional<
std::is_reference<T1>::value || std::is_reference<T2>::value,
cond_t<T1, T2>,
typename std::remove_reference<cond_t<T1 &, T2 &>>::type>::type;
int main()
{
using t1 = common<int,int>;
using t2 = common<const int, int>;
using t3 = common<int, int &>;
using t4 = common<int &, int &>;
using t5 = common<int &, int const &>;
static_assert( std::is_same<t1, int>::value, "!" );
static_assert( std::is_same<t2, int const>::value, "!" );
static_assert( std::is_same<t3, int>::value, "!" );
static_assert( std::is_same<t4, int &>::value, "!" );
static_assert( std::is_same<t5, int const &>::value, "!" );
}
Taking inspiration from Oliv's solution, a possible C++11 version
#include <utility>
#include <type_traits>
template <typename T1, typename T2>
using cond_t = decltype(false ? std::declval<T1>() : std::declval<T2>());
template <typename T1, typename T2>
using common = typename std::conditional<
std::is_reference<T1>::value || std::is_reference<T2>::value,
cond_t<T1, T2>,
typename std::remove_reference<cond_t<T1 &, T2 &>>::type>::type;
int main()
{
using t1 = common<int,int>;
using t2 = common<const int, int>;
using t3 = common<int, int &>;
using t4 = common<int &, int &>;
using t5 = common<int &, int const &>;
static_assert( std::is_same<t1, int>::value, "!" );
static_assert( std::is_same<t2, int const>::value, "!" );
static_assert( std::is_same<t3, int>::value, "!" );
static_assert( std::is_same<t4, int &>::value, "!" );
static_assert( std::is_same<t5, int const &>::value, "!" );
}
edited Nov 21 '18 at 12:23
answered Nov 21 '18 at 11:00
max66max66
36.4k74165
36.4k74165
I would have selected this as the as the answer but it doesn't work for my version of visual studio. Still a good answer :) Upvoted
– bradgonesurfing
Nov 21 '18 at 11:36
add a comment |
I would have selected this as the as the answer but it doesn't work for my version of visual studio. Still a good answer :) Upvoted
– bradgonesurfing
Nov 21 '18 at 11:36
I would have selected this as the as the answer but it doesn't work for my version of visual studio. Still a good answer :) Upvoted
– bradgonesurfing
Nov 21 '18 at 11:36
I would have selected this as the as the answer but it doesn't work for my version of visual studio. Still a good answer :) Upvoted
– bradgonesurfing
Nov 21 '18 at 11:36
add a comment |
In c++20 you could use common_reference
, (there is an implementation in the range v3 library), but it needs some adaptation if none of the two types are reference:
template<class T,class U>
using common_t = conditional_t<is_reference_v<T> || is_reference_v<U>
,common_reference_t<T,U>
,remove_reference_t<common_reference_t<T&,U&>>>;
I need the solution for visual studio 2010 upwards but the answer is good info anyway :)
– bradgonesurfing
Nov 21 '18 at 10:27
add a comment |
In c++20 you could use common_reference
, (there is an implementation in the range v3 library), but it needs some adaptation if none of the two types are reference:
template<class T,class U>
using common_t = conditional_t<is_reference_v<T> || is_reference_v<U>
,common_reference_t<T,U>
,remove_reference_t<common_reference_t<T&,U&>>>;
I need the solution for visual studio 2010 upwards but the answer is good info anyway :)
– bradgonesurfing
Nov 21 '18 at 10:27
add a comment |
In c++20 you could use common_reference
, (there is an implementation in the range v3 library), but it needs some adaptation if none of the two types are reference:
template<class T,class U>
using common_t = conditional_t<is_reference_v<T> || is_reference_v<U>
,common_reference_t<T,U>
,remove_reference_t<common_reference_t<T&,U&>>>;
In c++20 you could use common_reference
, (there is an implementation in the range v3 library), but it needs some adaptation if none of the two types are reference:
template<class T,class U>
using common_t = conditional_t<is_reference_v<T> || is_reference_v<U>
,common_reference_t<T,U>
,remove_reference_t<common_reference_t<T&,U&>>>;
answered Nov 21 '18 at 10:22


OlivOliv
9,3071957
9,3071957
I need the solution for visual studio 2010 upwards but the answer is good info anyway :)
– bradgonesurfing
Nov 21 '18 at 10:27
add a comment |
I need the solution for visual studio 2010 upwards but the answer is good info anyway :)
– bradgonesurfing
Nov 21 '18 at 10:27
I need the solution for visual studio 2010 upwards but the answer is good info anyway :)
– bradgonesurfing
Nov 21 '18 at 10:27
I need the solution for visual studio 2010 upwards but the answer is good info anyway :)
– bradgonesurfing
Nov 21 '18 at 10:27
add a comment |
This can be hacked with decltype
https://godbolt.org/z/7xEv7Z
#include <type_traits>
// Use it to display the actual generated type
template <typename T> struct F;
template <typename T0,typename T1>
struct Common
{
typedef decltype(true ? ((T0)std::declval<T0>()) : ((T1)std::declval<T1>()) )
type;
};
// Perform tests
F<Common<int,int>::type> f0;
F<Common<int &,int>::type> f1;
F<Common<const int &, int &>::type> f2;
F<Common<const int &, int>::type> f3;
Gives the results as expected
aggregate 'F<int> f0' has incomplete type and cannot be defined
aggregate 'F<int> f1' has incomplete type and
aggregate 'F<const int&> f2' has incomplete
aggregate 'F<int> f3' has incomplete type and
I believe this will not give you the desired result for the casecommon<int, int>::type
as declval will always return a reference and the deduced type is, thus, going to be a reference…
– Michael Kenzel
Nov 21 '18 at 10:23
@MichaelKenzel: I thought I saw your answer here before. Why did you delete it?
– P.W
Nov 21 '18 at 10:26
You are right.int,int
give rvalue reference
– bradgonesurfing
Nov 21 '18 at 10:26
@P.W my answer was simply to usestd::common_type
which is, unfortunately, not correct asstd::common_type
will decay the arguments and just return plainint
in all the cases above…
– Michael Kenzel
Nov 21 '18 at 10:30
@MichaelKenzel A small fix to using decltype will make it work. Just need to C style cast the result of decltype back to the type we want. I fixed the solution
– bradgonesurfing
Nov 21 '18 at 10:41
|
show 6 more comments
This can be hacked with decltype
https://godbolt.org/z/7xEv7Z
#include <type_traits>
// Use it to display the actual generated type
template <typename T> struct F;
template <typename T0,typename T1>
struct Common
{
typedef decltype(true ? ((T0)std::declval<T0>()) : ((T1)std::declval<T1>()) )
type;
};
// Perform tests
F<Common<int,int>::type> f0;
F<Common<int &,int>::type> f1;
F<Common<const int &, int &>::type> f2;
F<Common<const int &, int>::type> f3;
Gives the results as expected
aggregate 'F<int> f0' has incomplete type and cannot be defined
aggregate 'F<int> f1' has incomplete type and
aggregate 'F<const int&> f2' has incomplete
aggregate 'F<int> f3' has incomplete type and
I believe this will not give you the desired result for the casecommon<int, int>::type
as declval will always return a reference and the deduced type is, thus, going to be a reference…
– Michael Kenzel
Nov 21 '18 at 10:23
@MichaelKenzel: I thought I saw your answer here before. Why did you delete it?
– P.W
Nov 21 '18 at 10:26
You are right.int,int
give rvalue reference
– bradgonesurfing
Nov 21 '18 at 10:26
@P.W my answer was simply to usestd::common_type
which is, unfortunately, not correct asstd::common_type
will decay the arguments and just return plainint
in all the cases above…
– Michael Kenzel
Nov 21 '18 at 10:30
@MichaelKenzel A small fix to using decltype will make it work. Just need to C style cast the result of decltype back to the type we want. I fixed the solution
– bradgonesurfing
Nov 21 '18 at 10:41
|
show 6 more comments
This can be hacked with decltype
https://godbolt.org/z/7xEv7Z
#include <type_traits>
// Use it to display the actual generated type
template <typename T> struct F;
template <typename T0,typename T1>
struct Common
{
typedef decltype(true ? ((T0)std::declval<T0>()) : ((T1)std::declval<T1>()) )
type;
};
// Perform tests
F<Common<int,int>::type> f0;
F<Common<int &,int>::type> f1;
F<Common<const int &, int &>::type> f2;
F<Common<const int &, int>::type> f3;
Gives the results as expected
aggregate 'F<int> f0' has incomplete type and cannot be defined
aggregate 'F<int> f1' has incomplete type and
aggregate 'F<const int&> f2' has incomplete
aggregate 'F<int> f3' has incomplete type and
This can be hacked with decltype
https://godbolt.org/z/7xEv7Z
#include <type_traits>
// Use it to display the actual generated type
template <typename T> struct F;
template <typename T0,typename T1>
struct Common
{
typedef decltype(true ? ((T0)std::declval<T0>()) : ((T1)std::declval<T1>()) )
type;
};
// Perform tests
F<Common<int,int>::type> f0;
F<Common<int &,int>::type> f1;
F<Common<const int &, int &>::type> f2;
F<Common<const int &, int>::type> f3;
Gives the results as expected
aggregate 'F<int> f0' has incomplete type and cannot be defined
aggregate 'F<int> f1' has incomplete type and
aggregate 'F<const int&> f2' has incomplete
aggregate 'F<int> f3' has incomplete type and
edited Nov 21 '18 at 10:40
answered Nov 21 '18 at 10:18
bradgonesurfingbradgonesurfing
16.3k1083151
16.3k1083151
I believe this will not give you the desired result for the casecommon<int, int>::type
as declval will always return a reference and the deduced type is, thus, going to be a reference…
– Michael Kenzel
Nov 21 '18 at 10:23
@MichaelKenzel: I thought I saw your answer here before. Why did you delete it?
– P.W
Nov 21 '18 at 10:26
You are right.int,int
give rvalue reference
– bradgonesurfing
Nov 21 '18 at 10:26
@P.W my answer was simply to usestd::common_type
which is, unfortunately, not correct asstd::common_type
will decay the arguments and just return plainint
in all the cases above…
– Michael Kenzel
Nov 21 '18 at 10:30
@MichaelKenzel A small fix to using decltype will make it work. Just need to C style cast the result of decltype back to the type we want. I fixed the solution
– bradgonesurfing
Nov 21 '18 at 10:41
|
show 6 more comments
I believe this will not give you the desired result for the casecommon<int, int>::type
as declval will always return a reference and the deduced type is, thus, going to be a reference…
– Michael Kenzel
Nov 21 '18 at 10:23
@MichaelKenzel: I thought I saw your answer here before. Why did you delete it?
– P.W
Nov 21 '18 at 10:26
You are right.int,int
give rvalue reference
– bradgonesurfing
Nov 21 '18 at 10:26
@P.W my answer was simply to usestd::common_type
which is, unfortunately, not correct asstd::common_type
will decay the arguments and just return plainint
in all the cases above…
– Michael Kenzel
Nov 21 '18 at 10:30
@MichaelKenzel A small fix to using decltype will make it work. Just need to C style cast the result of decltype back to the type we want. I fixed the solution
– bradgonesurfing
Nov 21 '18 at 10:41
I believe this will not give you the desired result for the case
common<int, int>::type
as declval will always return a reference and the deduced type is, thus, going to be a reference…– Michael Kenzel
Nov 21 '18 at 10:23
I believe this will not give you the desired result for the case
common<int, int>::type
as declval will always return a reference and the deduced type is, thus, going to be a reference…– Michael Kenzel
Nov 21 '18 at 10:23
@MichaelKenzel: I thought I saw your answer here before. Why did you delete it?
– P.W
Nov 21 '18 at 10:26
@MichaelKenzel: I thought I saw your answer here before. Why did you delete it?
– P.W
Nov 21 '18 at 10:26
You are right.
int,int
give rvalue reference– bradgonesurfing
Nov 21 '18 at 10:26
You are right.
int,int
give rvalue reference– bradgonesurfing
Nov 21 '18 at 10:26
@P.W my answer was simply to use
std::common_type
which is, unfortunately, not correct as std::common_type
will decay the arguments and just return plain int
in all the cases above…– Michael Kenzel
Nov 21 '18 at 10:30
@P.W my answer was simply to use
std::common_type
which is, unfortunately, not correct as std::common_type
will decay the arguments and just return plain int
in all the cases above…– Michael Kenzel
Nov 21 '18 at 10:30
@MichaelKenzel A small fix to using decltype will make it work. Just need to C style cast the result of decltype back to the type we want. I fixed the solution
– bradgonesurfing
Nov 21 '18 at 10:41
@MichaelKenzel A small fix to using decltype will make it work. Just need to C style cast the result of decltype back to the type we want. I fixed the solution
– bradgonesurfing
Nov 21 '18 at 10:41
|
show 6 more comments
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53409292%2fis-there-a-c-trait-to-find-the-most-restricted-type-between-two-types-in-c%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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