Should I use an object or type as trait? Edit: Disclaimer: I am new to templates and traits.
I apologize in advance if this is a bad question.

I am refactoring two similar classes with small differences strewn all over them into one template class (or I am trying to anyway).
This is something I just wrote. (I hope I didn't make any mistakes renaming everything.)

// declaration - empty
template &lt;typename SETTINGS&gt;
struct SettingsTraits;

// specialization for type CFoo
template &lt;&gt;
struct SettingsTraits&lt;CFoo&gt;
{
  typedef CFooRelated RelatedType;
  typedef CAttribute&lt;CFooRelated &gt; &amp; (CDataSource::*AttrGetter)();
  static CAttribute&lt;CFooRelated &gt; &amp; (CDataSource::*GetAttr)();
};

SettingsTraits&lt;CFoo&gt;::AttrGetter SettingsTraits&lt;CFoo&gt;::GetAttr = &amp;CDataSource::GetFooAttr;

// specialization for type CBar    
template &lt;&gt;
struct SettingsTraits&lt;CBar&gt;
{
  typedef CBarRelated RelatedType;
  typedef CAttribute&lt;CBarRelated&gt; &amp; (CDataSource::*AttrGetter)();
  static CAttribute&lt;CBarRelated&gt; &amp; (CDataSource::*GetAttr)();
};

SettingsTraits&lt;CBar&gt;::AttrGetter SettingsTraits&lt;CBar&gt;::GetAttr = &amp;CDataSource::GetBarAttr;


So that I can write something like this

CAttribute&lt;SettingsTraits&lt;SETTINGS&gt;::RelatedType&gt; attr = (datasource.*SettingsTraits&lt;SETTINGS&gt;::GetAttr)();


But now I am wondering if I shouldn't just have created two different structs and passed those as template parameters instead.

I imagine the calling code would end up looking like this:

CAttribute&lt;FooTraits::RelatedType&gt; attr = FooTraits::GetAttr(datasource);


So probably somewhat cleaner but I haven't tried it so I don't know if it will actually work.
(I should probably replace the function pointer with a simple one line function that calls the appropriate function for each type in any case.)

Which alternative should I chose? What are the benefits/drawbacks of each?

Does it even make sense to have functions in traits? Should I maybe just use free template functions instead?
Yes, the std way of doing things in C++ would be to provide static member functions of your traits type. Consider:

// declaration - empty
template &lt;typename SETTINGS&gt;
struct SettingsTraits;

// specialization for type CFoo
template &lt;&gt;
struct SettingsTraits&lt;CFoo&gt;
{
  typedef CFooRelated RelatedType;
  static CAttribute&lt;RelatedType&gt;&amp; GetAttrFrom(CDataSource&amp; ds) { return ds.GetFooAttr(); }
};

// specialization for type CBar    
template &lt;&gt;
struct SettingsTraits&lt;CBar&gt;
{
  typedef CBarRelated RelatedType;
  static CAttribute&lt;RelatedType&gt;&amp; GetAttrFrom(CDataSource&amp; ds) { return ds.GetBarAttr(); }
};

typedef SettingsTraits&lt;SETTINGS&gt; TRAITS;
CAttribute&lt;TRAITS::RelatedType&gt; attr = TRAITS::GetAttrFrom(datasource);


Notice that this way of doing things doesn't involve global objects or values at all; it's all done entirely within the type system. The compiler can look at the line TRAITS::GetAttrFrom(datasource) and statically know that it's equivalent to datasource.GetFooAttr(), which means the whole thing compiles down to a single call instruction. Your old code would have required a trip to memory in order to load the value of the pointer SettingsTraits&lt;CFoo&gt;::GetAttr.

Rule of thumb: you should never need to construct a type-traits object at all. If you do, you're probably doing it wrong.