There is something seemingly basic that puzzles me greatly. I am hoping
people might clarify something I totally fail to understand.
I've been using BOOST_STATIC_CONSTANT for ages (with GCC). Now I have
something seemingly non-controversial:
template<typename user_type>
struct impl_ptr
{
using yes_type = boost::type_traits::yes_type;
using no_type = boost::type_traits::no_type;
using ptr_type = typename std::remove_const
On 17/08/2017 11:22, Vladimir Batov wrote:
There is something seemingly basic that puzzles me greatly. I am hoping people might clarify something I totally fail to understand.
I've been using BOOST_STATIC_CONSTANT for ages (with GCC). Now I have something seemingly non-controversial:
template<typename user_type> struct impl_ptr { using yes_type = boost::type_traits::yes_type; using no_type = boost::type_traits::no_type; using ptr_type = typename std::remove_const
::type*; template<typename Y> static yes_type test (Y*, typename Y::impl_ptr_type* =nullptr); static no_type test (...);
BOOST_STATIC_CONSTANT(bool, value = (1 == sizeof(test(ptr_type(nullptr))))); };
When compiled with gcc-.5.4.0, both lines below pass:
BOOST_TEST(true == boost::impl_ptr<Shared>::value); BOOST_TEST(true == boost::impl_ptr<Shared const>::value);
The only difference between them is "const". However, when I compile with clang-4.0, the second (const) line passes. However, the first one fails! I refuse to believe it's a clang glitch. It must be me doing something really stupid. Help?!
I can't answer this specific question, but since you're targeting C++11
anyway, shouldn't you be using std:: type traits?
So, something like:
template <typename T>
class has_impl_ptr_type
{
template <typename T1>
static typename T1::impl_ptr_type test(int);
template <typename>
static void test(...);
public:
enum { value = !std::is_void
On 2017-08-17 10:19, Gavin Lambert via Boost wrote:
On 17/08/2017 11:22, Vladimir Batov wrote:
There is something seemingly basic that puzzles me greatly. I am hoping people might clarify something I totally fail to understand.
I've been using BOOST_STATIC_CONSTANT for ages (with GCC). Now I have something seemingly non-controversial:
template<typename user_type> struct impl_ptr { using yes_type = boost::type_traits::yes_type; using no_type = boost::type_traits::no_type; using ptr_type = typename std::remove_const
::type*; template<typename Y> static yes_type test (Y*, typename Y::impl_ptr_type* =nullptr); static no_type test (...);
BOOST_STATIC_CONSTANT(bool, value = (1 == sizeof(test(ptr_type(nullptr))))); };
When compiled with gcc-.5.4.0, both lines below pass:
BOOST_TEST(true == boost::impl_ptr<Shared>::value); BOOST_TEST(true == boost::impl_ptr<Shared const>::value);
The only difference between them is "const". However, when I compile with clang-4.0, the second (const) line passes. However, the first one fails! I refuse to believe it's a clang glitch. It must be me doing something really stupid. Help?!
I can't answer this specific question, but since you're targeting C++11 anyway, shouldn't you be using std:: type traits?
So, something like:
template <typename T> class has_impl_ptr_type { template <typename T1> static typename T1::impl_ptr_type test(int); template <typename> static void test(...); public: enum { value = !std::is_void
::value }; };
Thanks, Gavin. Is it how it is done these days? Nice. Incorporated. Many thanks... clang still fails... now I am starting to look suspiciously in clang's direction.
On 17/08/2017 12:45, Vladimir Batov wrote:
Thanks, Gavin. Is it how it is done these days? Nice. Incorporated. Many thanks... clang still fails... now I am starting to look suspiciously in clang's direction.
FYI, the complete program:
#include
On 2017-08-17 11:33, Gavin Lambert via Boost wrote:
On 17/08/2017 12:45, Vladimir Batov wrote:
Thanks, Gavin. Is it how it is done these days? Nice. Incorporated. Many thanks... clang still fails... now I am starting to look suspiciously in clang's direction.
FYI, the complete program:
#include
template <typename T> class has_impl_ptr_type { template <typename T1> static typename T1::impl_ptr_type test(int); template <typename> static void test(...); public: enum { value = !std::is_void
::value }; }; struct A {...};
struct B { typedef int impl_ptr_type; };
static_assert(!has_impl_ptr_type<A>::value, ""); static_assert( has_impl_ptr_type<B>::value, ""); static_assert( has_impl_ptr_type<B const>::value, "");
int main() { return 0; }
Compiles successfully for me with -std=c++11 on gcc 5.4.0 and clang 3.8.0, as well as VS2015.
So unless this is some kind of regression in clang-4, your problem probably lies elsewhere.
Indeed, when has_impl_ptr_type is a separate class, it works as you
tested. What I initially had was that test was/is part of impl_ptr
template <typename T>
struct impl_ptr
{ ...
enum { value = !std::is_void
On Wed, Aug 16, 2017 at 7:22 PM, Vladimir Batov wrote:
BOOST_TEST(true == boost::impl_ptr<Shared>::value); BOOST_TEST(true == boost::impl_ptr<Shared const>::value);
The only difference between them is "const". However, when I compile with clang-4.0, the second (const) line passes. However, the first one fails! I refuse to believe it's a clang glitch. It must be me doing something really stupid. Help?!
This is to detect a member 'impl_ptr_type' type? Just:
template
On 17/08/2017 13:27, Glen Fernandes wrote:
This is to detect a member 'impl_ptr_type' type? Just:
template
struct has_impl_ptr_type : boost::false_type { }; template<class T> struct has_impl_ptr_type : boost::true_type { };
That *is* a nicer way to do it. Requires a minimum of Boost 1.64 or C++17, though. (Or VS2015, apparently.)
On 2017-08-17 11:45, Gavin Lambert via Boost wrote:
On 17/08/2017 13:27, Glen Fernandes wrote:
This is to detect a member 'impl_ptr_type' type? Just:
template
struct has_impl_ptr_type : boost::false_type { }; template<class T> struct has_impl_ptr_type : boost::true_type { }; That *is* a nicer way to do it. Requires a minimum of Boost 1.64 or C++17, though. (Or VS2015, apparently.)
Yes, I liked it too. :-) Thanks, Glen.
On Wed, Aug 16, 2017 at 9:45 PM, Gavin Lambert via Boost wrote:
On 17/08/2017 13:27, Glen Fernandes wrote:
This is to detect a member 'impl_ptr_type' type? Just:
template
struct has_impl_ptr_type : boost::false_type { }; template<class T> struct has_impl_ptr_type That *is* a nicer way to do it. Requires a minimum of Boost 1.64 or C++17, though. (Or VS2015, apparently.)
*Nod* - since Vladimir's intent is proposing this library for Boost, I just assume that his library can assume Boost v.Latest. :) Glen
On 2017-08-17 12:14, Glen Fernandes via Boost wrote:
On Wed, Aug 16, 2017 at 9:45 PM, Gavin Lambert via Boost wrote:
On 17/08/2017 13:27, Glen Fernandes wrote:
This is to detect a member 'impl_ptr_type' type? Just:
template
struct has_impl_ptr_type : boost::false_type { }; template<class T> struct has_impl_ptr_type That *is* a nicer way to do it. Requires a minimum of Boost 1.64 or C++17, though. (Or VS2015, apparently.)
*Nod* - since Vladimir's intent is proposing this library for Boost, I just assume that his library can assume Boost v.Latest. :)
Thank again, Glen. I've incorporated your version. As a separate struct (as you and Gavin showed) all works now. Many thanks.
Boost - Dev mailing list wrote
On 17/08/2017 13:27, Glen Fernandes wrote:
This is to detect a member 'impl_ptr_type' type? Just:
template<class, class = void> struct has_impl_ptr_type : boost::false_type { }; template <class T> struct has_impl_ptr_type<T, boost::void_t<typename T::impl_ptr_type> > : boost::true_type { };
That *is* a nicer way to do it. Requires a minimum of Boost 1.64 or C++17, though. (Or VS2015, apparently.)
This only requires C++11; it doesn't work on earlier versions of MSVC because MSVC was (and still is) lagging behind on support for expression-SFINAE. -- View this message in context: http://boost.2283326.n4.nabble.com/BOOST-STATIC-CONSTANT-tp4698066p4698086.h... Sent from the Boost - Dev mailing list archive at Nabble.com.
On 17/08/2017 16:35, dodheim wrote:
Boost - Dev mailing list wrote
On 17/08/2017 13:27, Glen Fernandes wrote:
This is to detect a member 'impl_ptr_type' type? Just:
template<class, class = void> struct has_impl_ptr_type : boost::false_type { }; template <class T> struct has_impl_ptr_type<T, boost::void_t<typename T::impl_ptr_type> > : boost::true_type { };
That *is* a nicer way to do it. Requires a minimum of Boost 1.64 or C++17, though. (Or VS2015, apparently.)
This only requires C++11; it doesn't work on earlier versions of MSVC because MSVC was (and still is) lagging behind on support for expression-SFINAE.
std::void_t does not exist until C++17. However the VS2015 STL adds it anyway. boost::void_t does not exist until 1.64. However it only works on compilers that support expression-SFINAE (which is most C++11 compilers except VS, until VS2015). This is what I meant by the above.
On 08/17/17 08:33, Gavin Lambert via Boost wrote:
On 17/08/2017 16:35, dodheim wrote:
Boost - Dev mailing list wrote
On 17/08/2017 13:27, Glen Fernandes wrote:
This is to detect a member 'impl_ptr_type' type? Just:
template<class, class = void> struct has_impl_ptr_type : boost::false_type { }; template <class T> struct has_impl_ptr_type<T, boost::void_t<typename T::impl_ptr_type> > : boost::true_type { };
That *is* a nicer way to do it. Requires a minimum of Boost 1.64 or C++17, though. (Or VS2015, apparently.)
This only requires C++11; it doesn't work on earlier versions of MSVC because MSVC was (and still is) lagging behind on support for expression-SFINAE.
std::void_t does not exist until C++17. However the VS2015 STL adds it anyway.
boost::void_t does not exist until 1.64. However it only works on compilers that support expression-SFINAE (which is most C++11 compilers except VS, until VS2015).
Boost.Core has had enable_if_has_type for this purpose for a long time. By itself, neither void_t nor enable_if_has_type requires expression SFINAE. It will only require one in some uses, typically involving decltype, when you test if an expression is valid (i.e. has a type). It works with as far as C++03 with regard to testing for nested types.
On 8/16/2017 7:22 PM, Vladimir Batov via Boost wrote:
There is something seemingly basic that puzzles me greatly. I am hoping people might clarify something I totally fail to understand.
I've been using BOOST_STATIC_CONSTANT for ages (with GCC). Now I have something seemingly non-controversial:
template<typename user_type> struct impl_ptr { using yes_type = boost::type_traits::yes_type; using no_type = boost::type_traits::no_type; using ptr_type = typename std::remove_const
::type*; template<typename Y> static yes_type test (Y*, typename Y::impl_ptr_type* =nullptr); static no_type test (...);
BOOST_STATIC_CONSTANT(bool, value = (1 == sizeof(test(ptr_type(nullptr))))); };
When compiled with gcc-.5.4.0, both lines below pass:
BOOST_TEST(true == boost::impl_ptr<Shared>::value); BOOST_TEST(true == boost::impl_ptr<Shared const>::value);
The only difference between them is "const". However, when I compile with clang-4.0, the second (const) line passes. However, the first one fails! I refuse to believe it's a clang glitch. It must be me doing something really stupid. Help?!
Can you not use tti to do what you want to do ?
On 2017-08-17 12:26, Edward Diener via Boost wrote:
On 8/16/2017 7:22 PM, Vladimir Batov via Boost wrote:
There is something seemingly basic that puzzles me greatly. I am hoping people might clarify something I totally fail to understand.
I've been using BOOST_STATIC_CONSTANT for ages (with GCC). Now I have something seemingly non-controversial:
template<typename user_type> struct impl_ptr { using yes_type = boost::type_traits::yes_type; using no_type = boost::type_traits::no_type; using ptr_type = typename std::remove_const
::type*; template<typename Y> static yes_type test (Y*, typename Y::impl_ptr_type* =nullptr); static no_type test (...);
BOOST_STATIC_CONSTANT(bool, value = (1 == sizeof(test(ptr_type(nullptr))))); };
When compiled with gcc-.5.4.0, both lines below pass:
BOOST_TEST(true == boost::impl_ptr<Shared>::value); BOOST_TEST(true == boost::impl_ptr<Shared const>::value);
The only difference between them is "const". However, when I compile with clang-4.0, the second (const) line passes. However, the first one fails! I refuse to believe it's a clang glitch. It must be me doing something really stupid. Help?!
Can you not use tti to do what you want to do ?
Thanks, Ed. The code above was there for god-knows-how-long. I am reading TTI docs now to make sure to use it in the future. Tnx.
participants (6)
-
Andrey Semashev
-
dodheim
-
Edward Diener
-
Gavin Lambert
-
Glen Fernandes
-
Vladimir Batov